Python子类调用父类私有方法报错,如何正确实现调用?
你遇到的是Python的**名称修饰(Name Mangling)**机制导致的问题。Python中,以双下划线__开头的方法会被视为类的私有成员,解释器会自动把这类方法名转换成_类名__方法名的形式,目的是避免子类意外覆盖父类的私有方法。
你的父类Parent里的__updateValue方法,实际会被转换成_Parent__updateValue;而子类Child里调用self.__updateValue()时,解释器会去寻找_Child__updateValue,这个方法并不存在,所以抛出了AttributeError。
下面是几种可行的解决方法:
方案1:直接使用修饰后的方法名调用(不推荐,但可行)
既然知道了方法被修饰后的名字,你可以直接在子类里调用这个全名:
class Parent: def __init__(self) -> None: self.value = 0 def __updateValue(self): self.value +=1 class Child(Parent): def __init__(self) -> None: super().__init__() def stuff(self): self.value = 6 self._Parent__updateValue() # 直接使用修饰后的方法名
不过这种写法不推荐,因为破坏了私有封装的设计初衷,而且如果父类名称修改,这里也要同步修改,维护性较差。
方案2:将父类方法改为受保护的(推荐)
如果父类的方法需要被子类访问,更符合Python编程风格的做法是把方法改成单下划线开头(受保护成员),这样既明确表示“这是内部方法,不建议外部直接调用”,又允许子类合法访问:
class Parent: def __init__(self) -> None: self.value = 0 def _updateValue(self): # 单下划线标记为受保护方法 self.value +=1 class Child(Parent): def __init__(self) -> None: super().__init__() def stuff(self): self.value = 6 self._updateValue() # 子类直接调用受保护方法
方案3:通过super()正确调用
你提到用super().__updateValue()没解决问题,大概率是拼写失误?正常情况下,super()会返回父类的代理对象,调用它的方法时会跳过子类的名称修饰逻辑,直接访问父类的私有方法:
class Parent: def __init__(self) -> None: self.value = 0 def __updateValue(self): self.value +=1 class Child(Parent): def __init__(self) -> None: super().__init__() def stuff(self): self.value = 6 super().__updateValue() # 通过super调用父类私有方法
测试这段代码的话,childObject.value最终会变成7,说明方法调用成功。如果你的代码仍报错,检查下是否拼写错误,或是子类中定义了同名的__updateValue方法导致冲突。
另外,你代码最后一行print(childObject.atr)也会报错,因为类中并未定义atr属性,应该改成print(childObject.value)。
内容的提问来源于stack exchange,提问作者Max

