2016-06-20 7 views
0

私は2つのパラメータを返す関数fを持っています。この関数の後、私は最初のパラメータを使います。別の機能と一緒に物を接着するために2番目のものが必要ですg。だから私のコードは次のようになります。withステートメント内の関数呼び出しを隠す

a, b = f() 
# do stuff with a 
g(b) 

これは非常に反復的であるので、私は、私はRAIIのアプローチのようなものを使用することができます考え出しました。

with F() as a: 
    # do stuff with a 

ことだ:私はオブジェクトが死んでしまうときがわからないと、私の主な目標は、反復コードを取り除くことであるので、しかし、私はwithステートメントを使用していました。私は基本的に、__enter____exit__関数(と明らかに__init__関数)を提供するこの関数の周りにオブジェクトFを作成しました。

しかし、これを処理するための正しいPythonの方法であるかどうかはまだ分かりません。withステートメントは例外を処理するためのものだったからです。特にこの__exit__関数には3つの引数がありますが、私は現時点では使用していません。

編集(更なる説明): 私はf()を呼び出すたびに、私はbで何かをする必要があります。間に何が起こったかは関係ありません。私はg(b)と表現しました。そして、まさに私はwithステートメントで隠れています。だからプログラマは、f()の呼び出しのたびにg(b)と入力する必要はありません。#do stuff with aは長くなるかもしれないので、非常に混乱し混乱するかもしれません。

+0

* *それは非常に反復的ですか?問題が何であるか、コンテキストマネージャが最善の解決策であると考えた理由は明確ではありません。あなたがそのコードをたくさん使っているなら、パラメータを 'a'と' b'の関数にしてください。途中のビットが変更された場合、それを抽出できないと思うので、 'g'を呼び出す前に' a'で呼び出す関数である新しいパラメータを追加します(関数はPythonではファーストクラスです)。あなたが達成しようとしているもののあまり抽象的な例を教えてください。 'g' * do *とは何ですか? – jonrsharpe

+1

それは正確にどのように繰り返しているのか説明できますか?また、with文で 'b'をどのように使用していますか?個人的には、リソースのように見えるものには 'with'を使用する方が好きです。もう1つの方法はデコレータを使用する方法です。 – SuperSaiyan

+0

「g」とは何ですか?例外がスローされた場合でもそれは起こるはずですか?それが起こらないようにするには、別の種類のクリーンアップが代わりに行われるべきですか? – user2357112

答えて

1

もう少し神託の方法は、contextlibモジュールを使用することです。自分のクラスを__enter____exit__の関数で展開することはできません。

from contextlib import contextmanager 

def g(x): 
    print "printing g(..):", x 

def f(): 
    return "CORE", "extra" 

@contextmanager 
def wrap(): 
    a, b = f() 
    try: 
     yield a 
    except Exception as e: 
     print "Exception occurred", e 
    finally: 
     g(b) 
if __name__ == '__main__': 
    with wrap() as x: 
     print "printing f(..):", x 
     raise Exception() 

出力:

$ python temp.py 
printing f(..): CORE 
Exception occurred 
printing g(..): extra 
+0

間違った機能で '@ contextmanager'デコレータを貼り付けたと思います。 – user2357112

+0

ええ、それはコピー貼り付けの問題でした。修正しました、ありがとう! – SuperSaiyan

+0

うん、それは私が望んだことだ。しかし、もし私が(将来)例外を処理する必要があるなら、exitとentry関数を持つ自分の派手なクラスが必要でしょうか? – hr0m

1

あなたのコードを読んでいる人(またはあなたが6ヶ月間)の場合、コンテキストマネージャーはおそらくリソースの作成/初期化と閉鎖/削除を暗示していますが、私はそのイディオムを再作成することに非常に注意します。

あなたはむしろ、コンテキストマネージャよりも、構図を使用することができます。それを行うの

def func(a, b): 
    # do stuff with a & optionally b 

def new_f(do_stuff): 
    a, b = f() 
    do_stuff(a, b) 
    g(b) 


new_f(func) 
+0

であるこれは、オプションでいいですが、悲しいことではありません方法はもっと一般的です。複雑な 'do_stuff'として扱うことはできません。ただ一つの関数で扱うことはできません。 – hr0m

+0

あなたは常に複数の呼び出しを単一の関数に引き出すことができます。よく名前が付けられ、十分に文書化された関数は、大きなコードブロックよりも優れています。 –

関連する問題