发电机是否了解发电机功能?

时间:2016-12-24 02:04:08

标签: python scope reference generator

从生成器函数返回的生成器对象是否保留对函数对象的引用?换句话说,是否可以实现可以执行此操作的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__的方法。是否有可能,或者一旦创建了发电机,链路是否已经丢失?

1 个答案:

答案 0 :(得分: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。如您所见,weakref已被清除,如果gen_iter仍然引用gen,则不会发生。

类似地,您可以显示生成器迭代器不会保留对函数__dict__的引用,或任何其他参考链,它将允许它检索存储在函数& #39; s __dict__

>>> 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