在Python中,对象会包括一个引用计数器。当对象被赋值给一个变量时,计算器会递增。反之,当变量被删除时候,计算器便递减。当计数器的指为0时,表示我们不再使用对象并可以销毁对象。正常来说,删除对象时候会调用del()方法。

很多小伙伴可能觉得调用del x 会直接销毁对象,其实并非如此,我们可以通过官方文档查阅可以知道https://docs.python.org/2.0/ref/customization.html

1
2
3
4
5
__del__ (self)
Called when the instance is about to be destroyed. This is also called a destructor. If a base class has a __del__() method, the derived class's __del__() method must explicitly call it to ensure proper deletion of the base class part of the instance. Note that it is possible (though not recommended!) for the __del__() method to postpone destruction of the instance by creating a new reference to it. It may then be called at a later time when this new reference is deleted. It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.
Programmer's note: "del x" doesn't directly call x.__del__() -- the former decrements the reference count for x by one, and the latter is only called when its reference count reaches zero. Some common situations that may prevent the reference count of an object to go to zero include: circular references between objects (e.g., a doubly-linked list or a tree data structure with parent and child pointers); a reference to the object on the stack frame of a function that caught an exception (the traceback stored in sys.exc_traceback keeps the stack frame alive); or a reference to the object on the stack frame that raised an unhandled exception in interactive mode (the traceback stored in sys.last_traceback keeps the stack frame alive). The first situation can only be remedied by explicitly breaking the cycles; the latter two situations can be resolved by storing None in sys.exc_traceback or sys.last_traceback.

Warning: due to the precarious circumstances under which __del__() methods are invoked, exceptions that occur during their execution are ignored, and a warning is printed to sys.stderr instead. Also, when __del__() is invoked is response to a module being deleted (e.g., when execution of the program is done), other globals referenced by the __del__() method may already have been deleted. For this reason, __del__() methods should do the absolute minimum needed to maintain external invariants. Python 1.5 guarantees that globals whose name begins with a single underscore are deleted from their module before other globals are deleted; if no other references to such globals exist, this may help in assuring that imported modules are still available at the time when the __del__() method is called.

通过官方文档可以知:del x 不能直接调用x. del ()前者将x的引用计数递减1,后者仅在其引用计数达到零时调用。

以下简单举例说明:
1
2
3
4
5
6
7
In [1]: class Test:
...: def __del__(self):
...: print("Delete {id}".format(id=id(self)))
...:
In [2]: T=Test()
In [3]: del T
Delete 140514893069920
  • 无法直接销毁的情况:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
In [1]: class Test:
def __del__(self):
print("Delete {id}".format(id=id(self)))
...:

In [2]: l1=[Test()]

In [3]: l2=l1[:]

In [4]: id(l1),id(l2)
Out[4]: (139682913194208, 139682928632032)

In [5]: del l1

In [6]: del l2
Delete 139682913195000

总结:通过发现浅复制调用并不能直接删除对象,同时验证了调用del不一定就能直接触发del()销毁对象。

Comments

2018-05-28