2016-12-24 6 views
3

ジェネレータ関数から返されたジェネレータオブジェクトは、関数オブジェクトへの参照を保持していますか?換言すれば、これを行うことができmagic_fnを実現することができる:発電機は発電機の機能について知っていますか?

>>> def gen(): 
...  yield 1 
...  yield 2 
...  
>>> gen.attr = 'potato' 
>>> g = gen() 
>>> del gen 
>>> next(g) 
1 
>>> magic_fn(g, 'attr') 
'potato' 

ジェネレータがコードオブジェクト(g.gi_code)を参照し、フレーム(g.gi_frame)、及び名前(g.__name__)を有しています。コードオブジェクトは、gen.__code__と同じメモリアドレスを持っています。

しかし、まだガベージコレクションされていないと仮定すると、gen.__dict__にアクセスする方法が見つかりませんでした。それは可能ですか、または発電機が作られた直後にリンクが既に失われていますか?

答えて

3

ジェネレータイテレータはジェネレータ関数を参照しません。あなたはweakref.refを使用して、関数への弱参照を保持することで、これを見ることができます:通常の参照とは異なり

>>> import weakref 
>>> def gen(): 
...  yield 1 
... 
>>> ref = weakref.ref(gen) 
>>> gen_iter = gen() 
>>> del gen 
>>> ref() is None 
True 

weakref.refは、それが参照するもののコレクションを遅らせることはありません。指示対象(gen)がまだ生存していた場合、ref()genとなります。指示対象が収集された場合、ref()Noneです。ご覧のとおり、弱参照はクリアされました。gen_iterにはまだgenという参照がある場合は発生しません。

>>> class Dummy(object): 
...  pass 
... 
>>> def gen(): 
...  yield 1 
... 
>>> gen.attr = Dummy() 
>>> ref = weakref.ref(gen.attr) 
>>> gen_iter = gen() 
>>> del gen 
>>> ref() is None 
True 
+0

ありがとう:

同様に、あなたはジェネレータイテレータは関数の__dict__、または任意の他の参照チェーン、それは機能の__dict__に保存されたアイテムを取得しましょうということへの参照を保持していないことを示すことができます私はまた、「さようなら」を印刷する 'Dummy'に' __del__'を実装することによって収集されたことを知ることができました。 'weakref.ref'のこの使用法とそれがどのように機能するかについて、より多くの説明を追加できますか? – wim

+0

@wim:弱参照の説明を少し追加しました。 – user2357112

関連する問題