はい、Zen of Pythonは「フラットはネストよりも優れている」と述べていますが、私たちが気にかけているのはそれだけではありません。また、「単純は複雑よりも優れている」とも述べています。の美しさは、以下で説明するように、これらの原則の両方with
に実際に準拠していることです。
Python の機能について哲学的に熟考するときはいつでも、 Python Enhancement Proposals (PEP)を調べて、機能の背後にある動機について読む価値があるでしょう。この場合、PEP 343 -- 「with」ステートメントは、要約の中でそれを前もって述べています。
この PEP は、Python 言語に新しいステートメント "with" を追加して、try/finally ステートメントの標準的な使用法を排除できるようにします。
ステートメントを除外try/finally
すると、コードが単純になり、読みやすくなります。
ただし、 PEP 343は単純な構文糖衣を提供するだけではありません。コンテキスト マネージャー プロトコルを確立します。
ステートメント内の with キーワードの直後の式は「コンテキスト式」です。その式は、ステートメント本体の期間中にコンテキスト マネージャーが確立するランタイム環境に関する主要な手がかりを提供するからです。
コンテキスト マネージャー プロトコルを使用することで、API ライターは複雑さを隠し、マルチスレッド コンテキストでリソースを正しく取得/解放することができます。
with
しかし、このステートメントの真の美しさはPEP 343の例 12 に示されています。
過剰なインデントを避けるために、指定されたコンテキストを左から右に自動的にネストする「ネストされた」コンテキスト マネージャー。
コンテキスト マネージャーを使用するnested()
と、次のようなコードを取得できます。
with a as x:
with b as y:
with c as z:
# Perform operation
そしてそれをこれに変えます:
with nested(a, b, c) as (x, y, z):
# Perform operation
nested()
は Python 2.5 で導入されましたが、バージョン 2.7 の時点で、この複数のコンテキスト マネージャーの構文形式を支持して非推奨になっていることに注意してください。
with a as x, b as y, c as z:
# Perform operation
明らかに、これは単純で読みやすいだけでなく、ネストされたものよりもはるかにフラットです。したがって、使用with
は無爲のパスに従います:)
更新: Simeon Visser の回答に関するコメントへの回答として、複数のコンテキスト マネージャーを使用して一度に複数のファイルを開く場合、2 つ (またはそれ以上) のファイルの内容をまとめて圧縮する場合の例を次に示します。ファイルの 1 つが失敗すると、すべてが失敗し、開かれた各ファイルが適切に閉じられます。
from itertools import izip
with open("/etc/passwd") as a, open("/etc/group") as b, open("/etc/shadow") as c:
for lines in izip(a,b,c):
print map(lambda x: x.split(':')[0], lines)
この例を 2 回実行します。root として 1 回、通常のユーザーとして 1 回。このファイルを保存すると仮定すると、ziptogether.py
最初に root として起動してみると成功しますが、読み取り権限がないためsudo python ziptogether.py
、通常のユーザーとして起動すると失敗します。失敗した場合、コンテキスト マネージャーは、実行がステートメントのスコープ外に移動したときに、失敗する前に正常に開かれたファイルが適切に閉じられるようにします。python ziptogether.py
/etc/shadow
with