a = A() print("show globals after create a") print(globals()) # 从全局对象中能找到A() 'a': <__main__.A object at 0x7f04de263af0> del a # print("show globals after delete a") print(globals()) # 这时全局对象中已经找不到对象A()了 time.sleep(1) print("sleep end") print(a) # 无法访问引用

输出结果:

show globals after create a
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f04de3de4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'time': <module 'time' (built-in)>, 'A': <class '__main__.A'>, 'a': <__main__.A object at 0x7f04de263af0>}
A instance deleted
show globals after delete a
{'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7f04de3de4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__cached__': None, 'time': <module 'time' (built-in)>, 'A': <class '__main__.A'>}
sleep end
Traceback (most recent call last):
  File "/testcode/mem.py", line 15, in <module>
    print(a)
NameError: name 'a' is not defined

结果分析:

调完del命令,__del__方法被执行,对象立即被删除(引用次数为0)。

实验2: 删除被多次引用的对象

  • 在上面那个用例的基础上,用多个引用引用A的对象
  • 删除其中一个引用,观察对象是否被删除
  • 删除一个引用,只是那个引用被删除了,但是对象不会被删除。也就是__del__方法不会被调用。

    验证代码:

    import time
    class A:
        def __del__(self):
            print("delete instance of A")
    a = A()
    b = a
    c = a
    print("show globals after create a")
    print(globals())
    del a  # 执行完这一行之后对象没有被回收,因为并没有打印出 delete instance of A
    print("show globals after delete a")
    print(globals())  # 在globals 里面还能找到对象 'b': <__main__.A object at 0x7fe1ef0c2af0>, 'c': <__main__.A object at 0x7fe1ef0c2af0> ,对象还没有被回收
    time.sleep(1)
    print("after sleeping...")  # 打印完这句后 紧接着就打印了 delete instance of A ,也就是在 执行完 del b 和 del c 之后对象立即被回收了
    del b
    del c
    print("show globals after delete b and c")  # 执行到此处之前对象已经被回收
    print(globals())  # 打印的globals里已经找不到对象 A() 
    

    输出结果:

    show globals after create a
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fe1ef23d4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/testcode/mem.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'A': <class '__main__.A'>, 'a': <__main__.A object at 0x7fe1ef0c2af0>, 'b': <__main__.A object at 0x7fe1ef0c2af0>, 'c': <__main__.A object at 0x7fe1ef0c2af0>}
    show globals after delete a
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fe1ef23d4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/testcode/mem.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'A': <class '__main__.A'>, 'b': <__main__.A object at 0x7fe1ef0c2af0>, 'c': <__main__.A object at 0x7fe1ef0c2af0>}
    after sleeping...
    delete instance of A
    show globals after delete b and c
    {'__name__': '__main__', '__doc__': None, '__package__': None, '__loader__': <_frozen_importlib_external.SourceFileLoader object at 0x7fe1ef23d4c0>, '__spec__': None, '__annotations__': {}, '__builtins__': <module 'builtins' (built-in)>, '__file__': '/testcode/mem.py', '__cached__': None, 'time': <module 'time' (built-in)>, 'A': <class '__main__.A'>}
    

    结论:回收对象的方法

    编程时候,一个创建一个对象我们最好只设置一个引用指向它,当不需要这个对象时候用del删除这个引用就可以回收对应的对象了。

    以上实验在Python 3.8.12 和 Python 3.7.7 验证过。