Pythonでは、標準機能とコンテキストマネージャの両方として機能する多くの機能があります。Python:標準関数とコンテキストマネージャ?
my_file=open(filename,'w')
または
with open(filename,'w') as my_file:
どちらもあなたがする必要があるものは何でもするために使用することができmy_file
オブジェクトを与える:たとえばopen()
は、のいずれかとして呼び出すことができます。一般的には後者が好ましいが、前者もやりたいときがある。
私は__enter__
と__exit__
機能を持つクラスを作成することによって、または関数とyield
はなくreturn
に@contextlib.contextmanager
デコレータを使用するか、コンテキストマネージャを作成する方法を見つけ出すことができました。しかし、私がこれを行うと、私はもはや関数をまっすぐに使うことができません - たとえば、デコレータを使用して、私は_GeneratorContextManager
オブジェクトを返します。もちろん、クラスとして作成した場合、ジェネレータクラスのインスタンスを取得するだけで、基本的には同じものと見なすことができます。
したがって、関数、オブジェクト、またはコンテキストマネージャを返す関数、つまり_GeneratorContextManager
などを返す関数(またはクラス)を設計するにはどうすればよいですか?
編集:例えば
、私は(これは非常に単純化され)、次のような機能を持っていると言う:
def my_func(arg_1,arg_2):
result=arg_1+arg_2
return my_class(result)
ので、関数はそれらをものにし、引数の数をとり、そのスタッフの結果を使ってクラスを初期化し、それを返します。私がopen
を呼び出した場合、file
オブジェクトを持っているように、最終結果はmy_class
のインスタンスです。私は、コンテキストマネージャとしてこの機能を使用することができるようにしたい場合は、私はそうのようにそれを修正することができます。
@contextlib.contextmanager
def my_func(arg_1,arg_2):
result=arg_1+arg_2 # This is roughly equivalent to the __enter__ function
yield my_class(result)
<do some other stuff here> # This is roughly equivalent to the __exit__function
が、私はもはやmy_class
ときのインスタンスを取得していませんストレート関数として呼び出します。おそらく私は何か間違っているだけでしょうか?
編集2:私はそれに機能を追加する機能など、my_class
を完全に制御を持っているん
注意。以下の受け入れられた答えから、私の難しさは基本的な誤解から生まれたと推測することができました。私は何を呼んでも(上記の例ではmy_func
)、__exit__
と__enter__
の機能が必要でした。これは正しくありません。実際、コンテキストマネージャとして機能するためには、関数が関数を必要とする(上記の例ではmy_class
)を返すだけです。
'open'はクラスのインスタンスを返す関数です。 'myfile = open(filename)'または 'open(filename)as myfile'のどちらを使っても、それは同じクラスのインスタンスになります。何も変更されません。 – zondo
@zondo真実、私が書こうとしている機能です。しかし、 '@ contextlib.contextmanager'デコレータで関数をラップし、それを標準関数として呼び出すと、戻ってきたクラスは関数からクラス" I "を返さないことになります。私がコンテクストマネージャーとして呼んだときだけ、そのクラスを取得します。簡単な例を追加します。 – ibrewster
あなたのクラスに '__call__'メソッドを定義してください。 –