Python多继承场景下操作继承类变量出现NameError如何解决?
问题成因
- Python执行类定义块内的代码时,不会触发继承链的属性查找逻辑。只有通过
类名.属性、实例.属性的方式访问属性时,才会按照MRO(方法解析顺序),从当前类、父类的顺序匹配对应属性。 - 你在
Phone类的定义块内直接写Devices和Pocketdevices时,解释器只会在当前类定义的局部作用域、全局作用域中检索这两个名称,父类的类变量不属于这两个作用域范围,因此直接抛出NameError。 - 第一段代码可以正常运行的原因是:你通过实例
SamsungGalaxyS21.Devices访问属性,触发了继承链查找逻辑,沿着Phone→Pocketgadgets→Electronicdevice的顺序成功找到Devices变量。
正确实现方式
方法1:显式通过父类名访问类变量
适合继承关系固定的场景,直接指定父类名称读取对应类变量,逻辑最直观:
class Electronicdevice(): Devices = 100 class Pocketgadgets(Electronicdevice): Pocketdevices = 40 class Phone(Pocketgadgets): # 显式指定父类名访问对应类变量 Phones = Electronicdevice.Devices - Pocketgadgets.Pocketdevices SamsungGalaxyS21 = Phone() print(SamsungGalaxyS21.Phones) # 输出60
方法2:用@property装饰器动态计算
如果希望父类变量修改后,结果可以自动同步,可将计算逻辑做成实例属性,访问时会自动触发继承链查找:
class Electronicdevice(): Devices = 100 class Pocketgadgets(Electronicdevice): Pocketdevices = 40 class Phone(Pocketgadgets): @property def Phones(self): # self访问属性会自动走继承链查找逻辑 return self.Devices - self.Pocketdevices SamsungGalaxyS21 = Phone() print(SamsungGalaxyS21.Phones) # 输出60
方法3:类定义完成后再赋值类变量
如果不想硬编码父类名,也可以在类定义结束后再计算赋值,此时类已经完成继承配置,通过类名访问属性会触发MRO查找:
class Electronicdevice(): Devices = 100 class Pocketgadgets(Electronicdevice): Pocketdevices = 40 class Phone(Pocketgadgets): pass # 类定义完成后再赋值类变量 Phone.Phones = Phone.Devices - Phone.Pocketdevices SamsungGalaxyS21 = Phone() print(SamsungGalaxyS21.Phones) # 输出60
多继承场景注意事项
如果使用多继承(一个类同时继承多个父类),可通过类名.__mro__打印属性查找顺序,避免同名属性匹配到错误的父类变量。
内容的提问来源于stack exchange,提问作者Aditi
相关产品推荐
相关产品推荐

