2014-09-05 3 views
2

부모 (순환 참조)를 참조하는 "불필요한"멤버가 있기 때문에 개체가 삭제되지 않는 refcount 문제가 발생했습니다. 드라이버 특정 물건을하기 위해참조하지 않고 부모 개체에 액세스

class User(object): 
    __slots__ = ("driver") 
    def __init__(self, *params): 
     self.driver = getDriverType(params)() 
     self.driver.parent = self 

    def getFancyObject(self): 
     return FancyObject(self) 

class Driver(object): 
    def __init__(self): 
     self.parent = None 
    def specialCode(self): 
     self.parent.getFancyObject() 
     ... 
     # driver-specific code doing something with fancyObject 

, 나는 여전히 (드라이버가 제공하는 기능을 통해 다시)에만 부모가 제공하는 고급 기능을 필요

다음은 단축 버전입니다. 나는 FancyObject 인스턴스없이 할 수 있었지만, 더 많은 코드를 입력해야했습니다.

물론 parent에 대한이 참조를 생성하면 부모와 드라이버가 모두 파기되지 않습니다.이 드라이버는 Python VM에서 RAM을 차지할뿐만 아니라이 드라이버가 처리하는 하드웨어 리소스도 차지합니다. Sunce가 User 인 모든 인스턴스가 남아 있으면이 문제는 신속하게 응답하지 않는 앱 및 메모리 부족 예외로 확대됩니다.

말할 필요도없이 클래스의 __slots__은 weakref.ref가 해당 클래스에서 만들어지지 않도록합니다.

필자는이 문제에 너무 빠져있어이 문제에 대한 훌륭한 Pythonic 솔루션을 볼 수 없습니다.

개체 GC를 방지하는 참조를 만들지 않고 원하는 기능을 어떻게 얻을 수 있습니까?

+0

"멋진 객체"를 검색 한 후 상위 참조를 삭제할 수 있습니까? – BrenBarn

+0

아니요, FancyObject를 요구하는 기능이 언제 호출 될지 모르겠습니다. 자주 호출 될 수도 있고 전혀 호출되지 않을 수도 있습니다. – velis

답변

2

개체가 __slots__으로 정의되어 있다는 사실이 해당 개체에 약한 참조를 생성하는 기능을 배제하지 않습니다. 그러나 당신이 명시 적으로 __weakref__ 속성을 정의 할 필요가 있다는 것을 의미합니다 :

class User: 
    __slots__ = ('driver','__weakref__') 
    def __init__(self): 
     self.driver = Driver() 
     self.driver.parent = weakref.ref(self) # or weakref.proxy(self) 
    def __del__(self): 
     print('user deleted') 

class Driver: 
    def __init__(self): 
     self.parent = None 
    def __del__(self): 
     print('driver deleted') 

>>> u = User() 
>>> del u 
user deleted 
driver deleted 
+1

IMO'ref' 대신'weakref.proxy'를 사용하는 것이 더 좋을 것입니다. 프록시는 특정 역 참조 (dereferencing)없이 실제 객체처럼 작동합니다. – lazy1

+1

'ref'의 사용은 OP의 주석에 기초한 예제였습니다 ... 요점은 당신이 명시 적으로'__weakref__' 슬롯을 만들 필요가 있다는 것입니다 (여러분이'ref' 또는'proxy'를 사용하든간에). – isedev

+0

고마워, 그리고 대결 프록시 대, lazy1 동의 :) – velis

관련 문제