为什么Python中继承tuple的子类__weakrefoffset__为0,继承list的为正值
问题解答
差异出现的核心原因
Python中一个类型是否支持弱引用,由该类型的__weakrefoffset__属性决定:只有这个值大于0时,类型的实例才可以被创建弱引用,这个值代表弱引用指针在实例内存布局中的偏移量。
内置的不可变类型(如tuple、int、str等)出于内存优化(比如小整数驻留、空元组/小元组缓存共享)和不可变性保证的需求,默认禁止子类自动生成__weakref__槽,所以哪怕继承tuple创建子类,默认的__weakrefoffset__依然是0,不支持弱引用。
而内置可变类型(如list、dict等)没有上述不可变约束和共享缓存机制,所以子类会自动分配__weakref__对应的内存偏移量,因此__weakrefoffset__大于0,支持弱引用。
和tuple使用__new__构建的关系
二者确实相关。不可变类型的实例完全由__new__方法完成内存分配和初始化,实例创建后不允许修改状态。如果默认给tuple子类自动添加__weakref__槽,会破坏内置tuple的内存布局结构,导致原有__new__的分配逻辑不兼容,也会影响不可变实例的缓存共享机制,所以Python默认做了限制。
实现支持弱引用的tuple子类
只需要在子类的__slots__中显式声明__weakref__即可,显式指定弱引用槽后,Python会自动设置对应的__weakrefoffset__,允许实例创建弱引用。
示例代码:
import weakref class TupleSupportWeakref(tuple): # 显式声明弱引用槽,也可以同时添加其他自定义槽位 __slots__ = ('__weakref__',) # 测试验证 t = TupleSupportWeakref([1, 2, 3]) t_proxy = weakref.proxy(t) print(t_proxy) # 正常输出 (1, 2, 3),无报错
内容的提问来源于stack exchange,提问作者Cesare Icarus
相关产品推荐
相关产品推荐

