【问题标题】:Does a generator know about the generator function?生成器是否知道生成器功能?
【发布时间】:2016-12-24 02:04:08
【问题描述】:

从生成器函数返回的生成器对象是否包含对该函数对象的引用?换句话说,是否有可能实现可以做到这一点的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__ 的方法。是否有可能,或者在创建生成器后链接已经丢失?

【问题讨论】:

    标签: python scope reference generator


    【解决方案1】:

    生成器迭代器不引用生成器函数。您可以通过使用 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__ 的引用,或任何其他可以让它检索存储在函数__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
    

    【讨论】:

    • 谢谢,我还可以通过在Dummy 上实现一个__del__ 来收集它,该Dummy 打印“再见”。您能否就weakref.ref 的用法及其工作原理添加更多解释?
    • @wim:添加了一些弱引用的解释。
    猜你喜欢
    • 1970-01-01
    • 2015-03-04
    • 2022-01-09
    • 2018-02-08
    • 2017-06-26
    • 2015-03-23
    • 2016-05-12
    相关资源
    最近更新 更多