为什么要调用python析构函数?

ppo*_*one 5 python

当我在解释器中键入它时,调用'y'似乎调用了析构函数?

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

y = SmartPhone()
y  #prints destroyed, why is that?
y  #object is still there
Run Code Online (Sandbox Code Playgroud)

这是一次运行,输出对我来说没有意义.

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>
>>>
Run Code Online (Sandbox Code Playgroud)

另外,调用'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
>>>
Run Code Online (Sandbox Code Playgroud)

fal*_*tru 13

有问题的输出仅在交互式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
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

  • 很棒的答案!我不知道_存在并且可能导致这样的麻烦.我发布了一个我用于实验的不同智能手机,但这是每个人都应该点击的答案. (2认同)

Bri*_*ian 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>
Run Code Online (Sandbox Code Playgroud)

请注意,这两个对象的地址不同.在destroyed当被印刷是__del__被称为上在第一个实例0x00000000021A5608.

在您的示例中,当您显式调用del对象引用时,它可能会立即被销毁(如果这是对象的唯一引用,并且GC立即发现它).当您执行y = SmartPhone()此操作时,旧对象可能不会立即被销毁,但是当收集器找到它并且看到引用计数为0时将被销毁.这通常几乎立即发生但可以延迟.

print 'destroyed'可以立即显示,也可以在会话中执行一个或多个附加命令后显示,但应该相当快.

  • 在Python中没有"在对象上调用`del`"这样的东西.因此,您无法使用`del`立即销毁对象.`del`的作用是删除**名称**.也就是说,它将**一个引用**移除到一个对象.然后,当垃圾收集器四处走动并检查每个对象有多少引用时,如果一个对象具有零引用,则它只会被销毁.请注意,如果您没有显式调用垃圾收集器,它可以随时运行,可以立即运行,也可以在一段时间之后运行. (2认同)