2016-12-24 1 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입니다. 보시다시피 weakref가 지워졌는데 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

관련 문제