Содержит ли объект-генератор, возвращаемый функцией-генератором, ссылку на объект-функцию? Другими словами, можно ли реализовать 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
wim 24 Дек 2016 в 05:04

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
4
user2357112 supports Monica 24 Дек 2016 в 05:32
Спасибо, я также смог увидеть, как это собрано, реализовав __del__ на Dummy, который печатает "до свидания". Не могли бы вы добавить дополнительные объяснения этого использования weakref.ref и того, как это работает?
 – 
wim
24 Дек 2016 в 05:23
@wim: Добавлено небольшое объяснение слабых ссылок.
 – 
user2357112 supports Monica
24 Дек 2016 в 05:32