2012-02-17 3 views
7

간단한 플랫폼 게임을 작성 중이며 '고스트'인스턴스를 제거 할 때 해당 인스턴스가 지속되고 가비지 수집되지 않습니다. 그것은 모든 참조를 제거하고 있지만 유령 개체가 가비지 수집되는 것을 방지하는 일종의 내부 참조를 가지고있는 것 같습니다. 특히 메서드 스위치 인 특성이 있습니다.내부 참조가 가비지 수집을 막습니다.

import weakref 

weak_ghosts = weakref.WeakKeyDictionary() 

class Ghost(object): 
    def __init__(self): 
     #pass 
     self.switch = {'eat':self.eat, 'sleep':self.sleep} 

    def eat(self): 
     pass 

    def sleep(self): 
     pass 

ghost = Ghost() 
weak_ghosts[ghost] = None 
#ghost.switch = {} # uncomment this line and ghost is successfully removed 
del ghost 
print "number of ghosts =", len(weak_ghosts) 

#output: 
number of ghosts = 1 

질문 :

  1. 실제로 무슨 일

    다음 코드는 내 문제를 보여?

  2. 이 상황을 피하려면 어떻게해야합니까?
  3. 전환 가능한 사전 사전을 만드는 올바른 방법론을 사용하고 있습니까?

답변

4

self.switch이 생성 한 순환 참조가 있습니다. 이 체크 아웃 :

import weakref 

class Ghost(object): 
    def __init__(self): 
     #pass 
     self.switch = {'eat':self.eat, 'sleep':self.sleep} 

    def eat(self): 
     pass 

    def sleep(self): 
     pass 

ghost = Ghost() 

def callback(o): 
    print 'callback', o 

wref = weakref.ref(ghost, callback) 
print 'del ghost' 
del ghost 
print 'after del ghost' 

인쇄 :

del ghost 
after del ghost 
callback <weakref at 00B55FC0; dead> 

그래서 실제 개체를 그냥 종료에 청소되었다.

GC를 수동으로 실행하여 효과를 볼 수 있습니다. 위의 스크립트 끝이 추가 :

print 'gc.collect' 
import gc 
gc.collect() 
print 'after gc.collect' 

지금 당신이 볼 수 있습니다 :

del ghost 
after del ghost 
gc.collect 
callback <weakref at 00B55FC0; dead> 
after gc.collect 

참고 기본적으로이 GC가 활성화되어 수시로 실행됩니다. 도달 할 수없는 순환 참조가되기 때문에 ghost 개체가 정리됩니다.

class Ghost(object): 
    def __init__(self): 
     self.switch = {'eat':Ghost.eat, 'sleep':Ghost.sleep} 

그래서 방법이 언 바운드 보관 :

2

옵션이하는 것입니다.

+1

그러나 실제로 그들을 호출 할 때 명시 적으로 개체를 전달해야합니다. –

관련 문제