Python删除实例后弱引用失效、删除类后实例弱引用仍生效的原因
Python weakref与类实例引用关系底层原理说明
Python中所有对象的生命周期由强引用计数决定,弱引用weakref.ref不会增加目标对象的强引用计数,一旦目标对象的强引用计数归零,对象会被垃圾回收器销毁,对应的弱引用解引用时就会返回None。
场景1:删除实例后弱引用失效的原因
创建实例test_ins = Test()时,该实例的强引用计数为1,weakref.ref(test_ins)创建的弱引用不会增加计数。
当执行del test_ins时,删除了当前作用域中该实例的唯一强引用,实例的强引用计数归零直接被销毁,因此test_ins_weakref()返回None,调用hello方法自然会报错。
场景2:删除类名不影响已有实例运行的原因
定义class Test的时候,本质上做了两件事:
- 在内存中生成了一个
Test类对象,存储类的所有方法、静态属性 - 在当前作用域创建了一个名为
Test的变量,指向这个内存中的类对象,这是类对象的其中一个强引用
每个Test实例创建后,都会在内部通过__class__属性持有类对象的强引用,这个引用和当前作用域的Test变量没有绑定关系。
当执行del Test时,只是删除了当前作用域里Test这个变量和类对象的绑定关系,类对象的强引用计数并没有归零——所有已经创建的Test实例都还持有它的强引用,所以类对象不会被销毁。
因此:
- 已有实例可以正常调用
hello方法,因为类对象还在内存中,方法查找逻辑正常 - 直接调用
Test()报NameError,是因为当前作用域已经找不到名为Test的变量,不是类对象被销毁了 - 调用
type(test_ins)()可以创建新实例,是因为type(test_ins)就是从实例的__class__属性拿到了内存中存活的类对象
类与实例的内存引用关系总结
- 类对象和实例对象是内存中两个独立的存储单元
- 实例对类对象有单向强引用,类对象不会持有单个实例的引用(除非手动在类里存储实例)
- 作用域中的类名只是指向类对象的一个强引用,不是类对象本身
- 类对象的销毁条件是所有指向它的强引用都被删除:包括作用域的类名变量、所有存活实例的
__class__引用、其他显式绑定的类对象引用
内容的提问来源于stack exchange,提问作者0Interest
相关产品推荐
相关产品推荐

