python with
ブロックを使って実験して、そのブロック内のアクションに修飾子を適用したいと思います。しかし、コルーチンの存在下でこれを分かりやすく行うことが可能かどうかはわかりません。例えばPython `with`コンテキストとジェネレータ/コルーチン/タスク
は、私は一時的にこのようなスタックにプッシュしWithContext
オブジェクトがあるとします。
class WithContext:
stack = []
def __init__(self, val):
self.val = val
def __enter__(self):
WithContext.stack.append(self.val)
def __exit__(self, exc_type, exc_val, exc_tb):
WithContext.stack.pop()
def do_scoped_contextual_thing():
print(WithContext.stack[-1])
を(明らかにスタックメンバーは、スレッドローカルでなければならないが、今のためにそれを無視します。)
次に、このコードは:
with WithContext("a"):
do_scoped_contextual_thing()
with WithContext("b"):
do_scoped_contextual_thing()
with WithContext("c"):
do_scoped_contextual_thing()
が印刷されます:
a
b
c
しかし、今、私はコルーチンの状況があるとします。私は出力にこのコードをしたい
def coroutine():
with WithContext("inside"):
yield 1
do_scoped_contextual_thing()
yield 2
with WithContext("outside"):
for e in coroutine():
do_scoped_contextual_thing()
print("got " + str(e))
を:
outside
got 1
inside
outside
got 2
しかし、実際には出力は以下となります。
inside
got 1
inside
inside
got 2
外側が__enter__
の内側にあるので内側に変わったコルーチンはスタックの上に値を置き、__exit__
は、コルーチンが終了するまで呼び出されません(コルーチンの中に出入りする際に常に入り口と出口がありません)。
この問題を回避する方法はありますか? 「コルーチンローカル」変数はありますか?
グローバルな可変状態(ここでは 'WithContext.stack')はありません。代わりにそれを渡す。 'for e in coroutine(stack):do_scoped_contextual_thing(stack)'ここで 'stack'は不変です。 – Ryan
あなたはコンテキストの結果についてアクセサーを考えましたか? WithContext( 'outside')のような 'のようなもの:' ... 'outside.do_scoped_contextual_thing()'? –
@ライアンはい、私は欠点を認識しています。私はまだそれを試してみたい。 –