ホームページ  >  記事  >  バックエンド開発  >  Pythonでのwithの使い方について

Pythonでのwithの使い方について

不言
不言オリジナル
2018-04-09 11:43:002852ブラウズ

この記事では、Python での with の使い方を紹介します。必要な方は参考にしてください。


1. With ステートメントとは何ですか?


事前に設定する必要があるタスクがいくつかあります。 . その後掃除をします。このシナリオでは、Python の with ステートメントが非常に便利な対処方法を提供します。良い例はファイル処理です。ファイル ハンドルを取得し、ファイルからデータを読み取り、ファイル ハンドルを閉じる必要があります。

with ステートメントが使用されない場合、コードは次のようになります:

file = open("/tmp/foo.txt")
data = file.read()file.close()

ここには 2 つの問題があります:

まず、ファイル ハンドルを閉じるのを忘れる可能性があります。
次に、ファイルからデータを読み取るときに例外が発生します。となり、処理は実行されません。

例外を処理する拡張バージョンは次のとおりです:

try:
    f = open('xxx')except:
    print 'fail to open'
    exit(-1)try:    do somethingexcept:    do somethingfinally:
     f.close()

このコードはうまく機能しますが、冗長すぎます。

今回はwithの腕の見せどころです。 with は、より洗練された構文を備えていることに加えて、コンテキストによって生成された例外も非常に適切に処理できます。

以下は with バージョンのコードです:

with open("/tmp/foo.txt") as file:
    data = file.read()

2. with はどのように機能しますか?

with の直後のステートメントが評価された後、返されたオブジェクトの __enter__() メソッドが呼び出され、戻り値が返されます。このメソッドにはasの後に変数を与えます。
with に続くすべてのコード ブロックが実行されると、以前に返されたオブジェクトの __exit__() メソッドが呼び出されます。

次の例は、 with がどのように機能するかを具体的に示しています:

#!/usr/bin/env python# with_example01.pyclass Sample:
    def __enter__(self):
        print "In __enter__()"
        return "Foo"
    def __exit__(self, type, value, trace):
        print "In __exit__()"def get_sample():
    return Sample()with get_sample() as sample:    print "sample:", sample

コードを実行すると、出力は次のようになります

bash-3.2$ ./with_example01.pyIn __enter__()sample: FooIn __exit__()

正如你看到的: 1. __enter__()方法被执行 2. __enter__()方法返回的值 - 这个例子中是”Foo”,赋值给变量’sample’ 3. 执行代码块,打印变量”sample”的值为 “Foo” 4. __exit__()方法被调用 
with真正强大之处是它可以处理异常。可能你已经注意到Sample类的 __exit__ 方法有三个参数 val, type 和 trace。 这些参数在异常处理中相当有用。我们来改一下代码,看看具体如何工作的。

#!/usr/bin/env python# with_example02.pyclass Sample:
    def __enter__(self):
        return self    def __exit__(self, type, value, trace):
        print "type:", type        print "value:", value        print "trace:", trace    def do_something(self):
        bar = 1/0
        return bar + 10with Sample() as sample:
    sample.do_something()

这个例子中,with后面的get_sample()变成了Sample()。这没有任何关系,只要紧跟with后面的语句所返回的对象有 __enter__() 和 __exit__() 方法即可。此例中,Sample()的 __enter__() 方法返回新创建的Sample对象,并赋值给变量sample。

代码执行后:

bash-3.2$ ./with_example02.py
type: <type &#39;exceptions.ZeropisionError&#39;>value: integer pision or modulo by zerotrace: <traceback object at 0x1004a8128>
Traceback (most recent call last):
  File "./with_example02.py", line 19, in <module>
    sample.do_something()
  File "./with_example02.py", line 15, in do_something
    bar = 1/0ZeropisionError: integer pision or modulo by zero

实际上,在with后面的代码块抛出任何异常时,__exit__() 方法被执行。正如例子所示,异常抛出时,与之关联的type,value和stack trace传给 __exit__() 方法,因此抛出的ZeropisionError异常被打印出来了。开发库时,清理资源,关闭文件等等操作,都可以放在 __exit__ 方法当中。

另外,__exit__ 除了用于tear things down,还可以进行异常的监控和处理,注意后几个参数。要跳过一个异常,只需要返回该函数True即可。

下面的样例代码跳过了所有的TypeError,而让其他异常正常抛出。

def __exit__(self, type, value, traceback):
    return isinstance(value, TypeError)

上文说了 __exit__ 函数可以进行部分异常的处理,如果我们不在这个函数中处理异常,他会正常抛出,这时候我们可以这样写(python 2.7及以上版本,之前的版本参考使用contextlib.nested这个库函数):

try:    with open( "a.txt" ) as f :        do something
except xxxError:    do something about exception

总之,with-as表达式极大的简化了每次写finally的工作,这对保持代码的优雅性是有极大帮助的。

如果有多个项,我们可以这么写:

with open("x.txt") as f1, open(&#39;xxx.txt&#39;) as f2:    do something with f1,f2

因此,Python的with语句是提供一个有效的机制,让代码更简练,同时在异常产生时,清理工作更简单。

3. 関連用語

with ステートメントを使用するには、まずコンテキスト マネージャーの概念を理解する必要があります。コンテキスト マネージャーを使用すると、with ステートメントが機能します。
以下は、コンテキスト マネージャーとステートメントに関連する一連の概念です。
コンテキスト管理プロトコル: メソッド __enter__() と __exit__() が含まれています。このプロトコルをサポートするオブジェクトは、これら 2 つのメソッドを実装する必要があります。
Context Manager: コンテキスト管理プロトコルをサポートするオブジェクト。このオブジェクトは __enter__() メソッドと __exit__() メソッドを実装します。コンテキスト マネージャーは、with ステートメントの実行時に確立されるランタイム コンテキストを定義し、with ステートメント ブロックのコンテキストで開始操作と終了操作を実行する責任を負います。コンテキスト マネージャーは通常、with ステートメントを使用して呼び出されますが、そのメソッドを直接呼び出して使用することもできます。
ランタイムコンテキスト: コンテキストマネージャーによって作成され、コンテキストマネージャーの __enter__() および __exit__() メソッドによって実装されます。 __enter__() メソッドは、ステートメント本体が実行される前にランタイムコンテキストに入ります。 __exit__() ランタイムコンテキストを終了します。ステートメント本体の実行後。 with ステートメントは、実行時コンテキストの概念をサポートします。
コンテキスト式: with ステートメント内のキーワード with に続く式。コンテキスト マネージャー オブジェクトを返します。
ステートメント本体 (with-body): with ステートメントでラップされたコード ブロックは、ステートメント本体の実行前にコンテキスト マネージャーの __enter__() メソッドを呼び出し、ステートメント本体の実行後に __exit__() メソッドが実行されます。

関連リンク:
1.http://blog.kissdata.com/2014/05/23/python-with.html
2.https://www.ibm.com/developerworks/cn/opensource/os -cn-pythonwith/

関連する推奨事項:

Python の with ステートメントを理解する方法

focus-within の使用方法の詳細な説明


以上がPythonでのwithの使い方についての詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。