Python子类访问父类__slots__槽变量报AttributeError
问题产生原因
dir()列出属性名不代表实例已经为该属性完成赋值。__slots__的本质是在类层级为实例声明固定的属性存储槽位,会为每个槽生成对应的数据描述符,只要类或任意父类在__slots__中声明了某属性,dir()就会将该属性名纳入输出列表。但槽位只是预留了存储空间,若从未给该属性赋值,槽的描述符在被访问时会直接抛出AttributeError,和普通实例属性未赋值就访问的报错逻辑一致。- 父类初始化逻辑完全未执行。你在
Child1的__init__方法中仅写了super(),这行代码仅生成了一个父类代理对象,没有调用任何方法,属于无效代码。Base1.__init__中给slot_0、slot_1赋值的逻辑从未被触发,两个槽位虽然存在,但始终没有被写入值,自然访问报错。
修复与正确访问方式
核心是要正确调用MRO链上所有类的初始化方法,保证父类中为槽赋值的逻辑正常执行,修复后的代码如下:
class Base1(): __slots__ = ["slot_0", "slot_1"] def __init__(self): self.slot_0 = "zero" self.slot_1 = "one" super().__init__() # 多继承场景下需要调用,保证MRO链后续类初始化执行 def baseFunc(self): print("nice1") class Base2(): __slots__ = [] def __init__(self): super().__init__() pass def baseFunc2(self): print("nice2") class Child1(Base1, Base2): __slots__ = ["slot_00", "slot_11"] def __init__(self): self.slot_00 = "zero" self.slot_11 = "one" super().__init__() # 正确调用父类初始化方法,而非仅写super() def newFunc(self): print("nice") c1 = Child1() print(c1.slot_0) # 正常输出 zero print(c1.slot_1) # 正常输出 one
如果不需要父类给槽设置默认值,也可以在实例化子类后手动给继承来的槽位赋值,赋值后即可正常访问:
c1 = Child1() c1.slot_0 = "自定义值" print(c1.slot_0) # 正常输出 自定义值
注意:不存在“子类无法访问父类定义的槽变量”的限制,只要子类没有在自身
__slots__中声明同名属性覆盖父类槽,就可以正常读写父类声明的槽位,唯一前提是该槽位已经被赋值。
内容的提问来源于stack exchange,提问作者ThreadBucks
相关产品推荐
相关产品推荐

