簡體   English   中英

為什么要調用python析構函數?

[英]Why is the python destructor being called?

當我將其輸入解釋器時,調用“ y”似乎會調用析構函數?

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>
>>>

另一個調用“ del y”有時調用析構函數,有時不調用

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
>>>

有問題的輸出僅在交互式shell中復制。

在交互式會話中,存在附加變量_ ,它引用最后一個值。

使用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

23在上面的輸出應為12 它們以這種方式打印,因為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

您必須在同一解釋器會話中重置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狀態是在第一個實例0x00000000021A5608上調用__del__時。

在您的示例中,當您在對象引用上顯式調用del時,它可能會立即被銷毀( 如果這是對該對象的唯一引用,並且GC立即找到了它 )。 當您執行y = SmartPhone() ,舊對象可能不會立即被銷毀,但在收集器找到並看到引用計數為0時,它將被銷毀。這通常幾乎立即發生,但可以延遲。

您的print 'destroyed'可能會立即顯示,或者可能在您的會話中執行了1個或更多其他命令后顯示,但應該很快發生。

我運行了相同的代碼,但是得到了不同的結果:

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>

__del__不是C ++的析構函數。 這是一種保證在對象銷毀之前和對象變得能夠被垃圾回收之后運行的方法。

在CPython中,當引用計數達到0時會發生這種情況。因此,如果使用__del__方法將值重新分配給保存對象的單個變量,則此對象的該方法將在此后不久調用。

擴展@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
>>> 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM