python中的 __del__ 方法:销毁对象

函数中的__del__() 方法: 销毁对象
Python 通过调用__init__()方法构造当前类的实例化对象,而__del__() 方法,是用来销毁实例化对象。
事实上在编写程序时,如果之前我们创建的类实例化对象后续程序不再使用,最好在合适位置手动将其销毁,释放其占用的内存空间(整个过程称为垃圾回收 (简称:GC))。

大多数情况下,Python开发者不需要手动进行垃圾回收,因为Python有自动的垃圾回收机制,能将不需要使用的实例对象进行销毁。

实例一

# -*- coding:utf8 -*-class User:
def __init__(self):
print("=== 调用 __init__() 方法构造对象 ===")
def __del__(self):
print("调用__del__() 销毁对象,(对象占用的内存被回收)")
u1 = User()
print('#'*50)

运行结果:

D:\pythonproject\venv\Scripts\python.exe D:/pythonproject/私有属性2.py
=== 调用 __init__() 方法构造对象 ===
##################################################
调用__del__() 销毁对象,(对象占用的内存被回收)
Process finished with exit code 0

注释:上面代码在交互式python编程下运行是不会调用__del__()方法的,也就不会打印出 调用__del__() 销毁对象,(对象占用的内存被回收),因为程序没有结束。

结论:Python 会在程序即将结束前调用__del__()方法,自动帮我们销毁对象,进而释放对象占用的内存,注意__del__()方法调用的位置,在print(’#’*50)语句之后。

实例二

# -*- coding:utf8 -*-class User:
def __init__(self):
    print("=== 调用 __init__() 方法构造对象 ===")
def __del__(self):
    print("调用__del__() 销毁对象,(对象占用的内存被回收)")
u1 = User()
del u1
print('#'*50)

运行结果:

D:\pythonproject\venv\Scripts\python.exe D:/pythonproject/私有属性2.py
=== 调用 __init__() 方法构造对象 ===
调用__del__() 销毁对象,(对象占用的内存被回收)
##################################################
Process finished with exit code 0

结论:手动删除对象,进而调用__del__() 方法销毁内存对象,释放内存空间。

实例三

# -*- coding:utf8 -*-class User:
def __init__(self):
print("=== 调用 __init__() 方法构造对象 ===")
def __del__(self):
print("调用__del__() 销毁对象,(对象占用的内存被回收)")
u1 = User()
u2 = u1# 
del u1 # 从运行结果可以看出来,执行该语句没有调用 __del__()方法,而是在程序即将运行结束的时候,程序自动调用了__del__()方法,销毁了对象
print('#'*50)# print('\n')# del u2# print("*"*50)

运行结果:

扫描二维码关注公众号,回复: 12236801 查看本文章
D:\pythonproject\venv\Scripts\python.exe D:/pythonproject/销毁对象3.py
=== 调用 __init__() 方法构造对象 ===
##################################################
调用__del__() 销毁对象,(对象占用的内存被回收)

Process finished with exit code 0

结论:从运行结果可以看出来,执行该语句 del u1 调用__del__()方法,但是并没有立即执行,而是在程序即将运行结束的时候,程序自动调用__del__()方法,销毁了内存对象,这里涉及 Python的垃圾回收机制。
Python采用自动引用计数(简称:ARC(auto-refrence-count))的方式实现垃圾回收机制。该方法的核心思想是:每一个Python对象都会配置一个计数器,初始Python实例对象的计数器值都为0,如果有变量引用该实例对象,其计数器的值也会加1,依次类推;反之,每当一个变量取消对该实例对象的引用,计数器会减1。如果一个Python对象的计数器值为0,则表明没有变量引用该Python对象,即证明程序不再需要它了,此时Python就会自动调用__del__()方法将其回收。

上面 实例三 分析:实际上构建 u1 实例对象的过程分为2步,先使用 User() 调用该类中的__init__() 方法构造出一个该类的对象(我们将其称为 U,计数器为0 ),并立即用 u1 这个变量作为所建实例对象的引用 (U 的计数器值 + 1)。在此基础上,又有一个 u2 变量引用 u1(其实相当于引用User(),此时U的计数器再 +1),这时如果调用 del u1 语句,只会导致 C 的计数器减 1(值变为1),因此C的计数器值不为0,因此U不会被销毁(不会执行__del__() 方法)。

实例四

# -*- coding:utf8 -*-class User:
def __init__(self):
print("=== 调用 __init__() 方法构造对象 ===")
def __del__(self):
print("调用__del__() 销毁对象,(对象占用的内存被回收)")
u1 = User()
u2 = u1del u1 # 从运行结果可以看出来,执行该语句没有调用 __del__()方法,而是在程序即将运行结束的时候,程序自动调用了__del__()方法,销毁了对象print('#'*50)
# print('\n')# del u2print("*"*50)

运行结果:

D:\pythonproject\venv\Scripts\python.exe D:/pythonproject/私有属性2.py
=== 调用 __init__() 方法构造对象 ===
##################################################
**************************************************
调用__del__() 销毁对象,(对象占用的内存被回收)
Process finished with exit code 0

实例五:

# -*- coding:utf8 -*-class User:
def __init__(self):
print("=== 调用 __init__() 方法构造对象 ===")
def __del__(self):
print("调用__del__() 销毁对象,(对象占用的内存被回收)")
u1 = User()
u2 = u1del u1 # 从运行结果可以看出来,执行该语句没有调用 __del__()方法,而是在程序即将运行结束的时候,程序自动调用了__del__()方法,销毁了对象print('#'*50)
print('\n')
del u2print("*"*50)

运行结果:

D:\pythonproject\venv\Scripts\python.exe D:/pythonproject/私有属性2.py
=== 调用 __init__() 方法构造对象 ===
##################################################
调用__del__() 销毁对象,(对象占用的内存被回收)
**************************************************
Process finished with exit code 0

通过 实例四实例五 两个实例对比,我们不难发现:实例对象被引用了n次,计数器就为n,执行一次 del 对象的引用 那么所引用的这个实例对象的计数器就会自动减1,当实例对象的计数器减为零时,就会调用并且执行类中的__del__()方法,计数器不为零,则不会执行实例对象中的__del__() 方法,那么就会等程序即将结束之前,python解释器会自动执行__del__() 方法,销毁对象。

猜你喜欢

转载自blog.csdn.net/weixin_48505120/article/details/107586395
今日推荐