2013-09-17 1 views
0

У меня возникла странная проблема при попытке удалить последнюю ссылку на объект.Странное удаление после удаления последней ссылки

Код:

import sys 
import weakref 

class Ref: 

    def __init__(self, name): 
     self.name = name 
     self.ref = [] 

    def reference(self, obj): 
     name = obj.name 
     self.ref.append(
      weakref.ref(obj, lambda wref: print('{!r} is dead.'.format(name)))) 


a = Ref('a') 
b = Ref('b') 
c = Ref('c') 
d = Ref('d') 

a.reference(b) 
b.reference(c) 
c.reference(d) 
d.reference(a) 

print('reference count before killed:', sys.getrefcount(d.ref[0]())) 
del a 
print('reference count after killed:', sys.getrefcount(d.ref[0]())) 

И выход таков:

reference count before killed: 2 
'a' is dead. 
reference count after killed: 1547 
'd' is dead. 
'c' is dead. 

Но иногда (это совершенно случайно) я получил только 'd' is dead. или 'c' is dead. (но никогда не 'b' is dead.), или ни этих сообщений вообще.

Так что мой первый вопрос: что это за странный счетчик ссылок 1547? И откуда оно взялось?

И второе: почему убивающий экземпляр a создает это случайное «убийство других экземпляров» эффект?

+2

Подсчет 1547, вероятно, является refcount of None, который вызывает слабыйref, как только реферируется. – user2357112

+0

О, это может быть ... спасибо;) –

+0

Вы используете это как скрипт или из интерактивной оболочки? Не гарантируется, будут ли уничтожены объекты, когда выйдет переводчик. – user2357112

ответ

2

После a is GC'd, d.ref[0]() производит None. Вот почему вы получаете скидку 1547 после удаления a; в конце концов, вы не можете потребовать пересчет собранного объекта, не так ли?

Странное удаление c и d связано с тем, что Python не гарантирует, будут ли объекты живыми, когда выход интерпретатора будет проходить через обычный процесс уничтожения. b, c и d все живы в конце вашего скрипта. Иногда они получат GC'd в обычном режиме, а вызовы weakref будут работать. Иногда этого не бывает. Питон не дает никаких обещаний.

+0

Я принимаю этот ответ, большое спасибо, однако, мне любопытно: знаете ли вы, что является правильным и безопасным решение для чего я хочу? Я имею в виду, что если я использую сильные ссылки во всем мире, я должен вручную убить все эти ссылки .. (и этот мой пример - это только фиктивный * вопросно-готов * версия исходных объектов .. –

+0

Я не помню. подумайте, что есть способ зарегистрировать обработчик, который будет запущен, когда переводчик выйдет, но я не помню, считается ли это хорошим способом справиться с этой проблемой. – user2357112