2013-07-10 3 views
5

Когда я ввожу это в интерпретатор, вызов 'y', кажется, вызывает деструктор?Почему вызывается деструктор python?

class SmartPhone: 
    def __del__(self): 
     print "destroyed" 

y = SmartPhone() 
y #prints destroyed, why is that? 
y #object is still there 

Вот один запуск, вывод не имеет смысла для меня.

C:\Users\z4>python 
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 
32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class SmartPhone: 
...  def __del__(self): 
...  print "destroyed" 
... 
>>> y = SmartPhone() 
>>> del y 
destroyed 
>>> y = SmartPhone() 
>>> y 
<__main__.SmartPhone instance at 0x01A7CBC0> 
>>> y 
<__main__.SmartPhone instance at 0x01A7CBC0> 
>>> y 
<__main__.SmartPhone instance at 0x01A7CBC0> 
>>> del y 
>>> y = SmartPhone() 
>>> y 
destroyed 
<__main__.SmartPhone instance at 0x01A7CB98> 
>>> 

и другой, называя «дель у» иногда вызывает деструктор, а иногда и не

C:\Users\z4>python 
Python 2.7.3 (default, Apr 10 2012, 23:31:26) [MSC v.1500 32 bit (Intel)] on win 
32 
Type "help", "copyright", "credits" or "license" for more information. 
>>> class SmartPhone: 
...  def __del__(self): 
...    print "destroyed" 
... 
>>> 
>>> y = SmartPhone() 
>>> 
>>> y 
<__main__.SmartPhone instance at 0x01B6CBE8> 
>>> y 
<__main__.SmartPhone instance at 0x01B6CBE8> 
>>> y 
<__main__.SmartPhone instance at 0x01B6CBE8> 
>>> del y 
>>> y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'y' is not defined 
>>> y = SmartPhone() 
>>> y 
destroyed 
<__main__.SmartPhone instance at 0x01B6CC38> 
>>> del y 
>>> y 
Traceback (most recent call last): 
    File "<stdin>", line 1, in <module> 
NameError: name 'y' is not defined 
>>> 
+14

Невозможно дублировать. –

+1

Можете ли вы опубликовать фактический вывод сценария? – thegrinner

+0

Вы уверены, что печатает «уничтожен» на этой строке, а не в конце скрипта? – Dahaka

ответ

6

вам необходимо сбросить значение y в том же сеансе интерпретатора, сбросив счетчик ссылок на исходный объект 0. Тогда, так как первый объект не ссылается, она разрушается, а новый объект ссылается y

>>> class SmartPhone: 
... def __del__(self): 
...  print 'destroyed' 
... 
>>> y = SmartPhone() 
>>> y 
<__main__.SmartPhone instance at 0x00000000021A5608> 
>>> y = SmartPhone() 
>>> y 
destroyed 
<__main__.SmartPhone instance at 0x00000000021A5648> 

Обратите внимание, что адрес этих двух объектов отличается. Печатается destroyed, когда __del__ вызывается в первом случае по адресу 0x00000000021A5608.

В вашем примере, когда вы явно вызвать del на ссылку на объект, он может быть уничтожены мгновенно (, если это единственная ссылка на объект и GC нашел его сразу). Когда вы сделаете y = SmartPhone(), старый объект, скорее всего, не будет немедленно уничтожен, но будет уничтожен, когда коллекционер найдет его и увидит счетчик ссылок 0. Это обычно происходит почти сразу, но может быть отложено.

+0

Во втором примере я дал. Почему «del y» не сразу вызвал деструктор? – ppone

+0

Поскольку, вероятно, временная ссылка на объект в другом месте, который не был очищен, как указывает @falsetru в своем ответе. – Brian

+2

В Python нет такой вещи, как «вызов' del' на объект ». Таким образом, вы не можете немедленно уничтожить объект, используя 'del'. Что 'del' делает, так это удалить ** имя **. То есть, он удаляет ** одну ссылку ** на объект. Затем, когда сборщик мусора идет и проверяет, сколько ссылок имеет каждый объект, если объект имеет нулевые ссылки, он только затем уничтожается. Обратите внимание: если вы явно не вызываете сборщик мусора, он может запускаться всякий раз, когда захочет, что может быть сразу или может быть через некоторое время. –

0

я запускал тот же самый код, но получил другой результат:

class SmartPhone: 
    def __del__(self): 
     print "destroyed" 

y = SmartPhone() 
del y 
print y #prints destroyed, why is that? 

Выход:

>>> 
destroyed 

Traceback (most recent call last): 
    File "C:/Users/Kulanjith/Desktop/rand.py", line 7, in <module> 
    print y #prints destroyed, why is that? 
NameError: name 'y' is not defined 

фактически del y делает свою работу, но вы вместо

>>> y = SmartPhone() # create object 
>>> del y # delete's the object y, therefore no variable exist after this line executes 
destroyed 
>>> y = SmartPhone() # again creates a object as a new variable y 
>>> y # since no __repr__ methods are define the outcome is normal 
<__main__.SmartPhone instance at 0x01A7CBC0> 
0

__del__ не является деструктор в смысле С ++. Это метод, который гарантированно запускается до уничтожения объекта и после того, как объект станет способным собирать мусор.

В CPython это происходит, когда счетчик ссылок достигает 0. Соответственно, если вы переназначить значение для единственной переменной, содержащей объект с помощью метода __del__, этот метод этого объекта будет вызываться вскоре после этого.

13

Этот вопрос реплицируется только в интерактивной оболочке.

В интерактивном сеансе существует дополнительная переменная _, которая относится к последнему значению.

Использование sys.getrefcount для проверки счетчика ссылок:

>>> import sys 
>>> class SmartPhone: 
...  def __del__(self): 
...  print "destroyed" 
... 
>>> y = SmartPhone() 
>>> sys.getrefcount(y) # not printed, _ does not reference SmartPhone object yet. 
2 
>>> y 
<__main__.SmartPhone instance at 0x000000000263B588> 
>>> sys.getrefcount(y) # y printed, _ reference SmartPhone object. 
3 

2, 3 в выводе выше должно быть 1, 2. Они печатаются таким образом, потому что getrefcount() временно увеличивает количество ссылок, как указано в документации getrefcount.


Я изменил SmartPhone следующим образом, чтобы было легко проверить, что происходит.

>>> class SmartPhone(object): 
...  def __init__(self, name): 
...   self.name = name 
...  def __repr__(self): 
...   return super(SmartPhone, self).__repr__() + ' name=' + self.name 
...  def __del__(self): 
...  print "destroyed", self 
... 
>>> y = SmartPhone('first') 
>>> del y # deleted immediately, because only "y" reference it. 
destroyed <__main__.SmartPhone object at 0x00000000024FEFD0> name=first 
>>> y = SmartPhone('second') 
>>> y # at this time, _ reference to second y (y's reference count is now 2) 
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second 
>>> y 
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second 
>>> y 
<__main__.SmartPhone object at 0x00000000024FEFD0> name=second 
>>> del y # not deleted immediately, because _ reference it. 
>>> y = SmartPhone('third') # _ still reference the second y, because nothing is printed. 
>>> y # second y is deleted, because _ now reference the third y. (no reference to the second y) 
destroyed <__main__.SmartPhone object at 0x00000000024FEFD0> name=second 
<__main__.SmartPhone object at 0x000000000264A470> name=third 
+2

Отличный ответ! Я понятия не имел, что существует и может вызвать такие проблемы. Я размещаю другой смартфон, который я использовал для экспериментов, но это ответ, который каждый должен щелкнуть. – tdelaney

+3

+1 Хорошо объяснено – Brian

+2

+1 Отличный ответ! –

0

Расширяя @ falsetru Ответим, вот SmartPhone, что делает его легко увидеть, что происходит.

myid = 0 

class SmartPhone(object): 
    def __init__(self): 
     global myid 
     self.myid = myid 
     print("init %d" % self.myid) 
     myid += 1 
    def __del__(self): 
     print("delete", self) 
    def __repr__(self): 
     return "repr %d" % self.myid 
    def __str__(self): 
     return "str %d" % self.myid 

>>> 
>>> y=SmartPhone() 
init 0 
>>> # _ will hold a ref to y 
... 
>>> 
>>> y 
repr 0 
>>> _ 
repr 0 
>>> # del only decreases the ref count 
... 
>>> del y 
>>> _ 
repr 0 
>>> # _ still refs 0 
... 
>>> y=SmartPhone() 
init 1 
>>> # but now i reassign _ and 0 goes away 
... 
>>> y 
delete str 0 
repr 1 
>>> 
Смежные вопросы