You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python子类继承中名称修饰(name mangling)的合理使用与问题解决

Python名称修饰(__)的使用误区与正确场景

问题背景

我尝试在Python中使用名称修饰(__)为类和子类创建“受保护”属性,但通过不同子类扩展功能时出现错误。当父类和子类各有独特使用场景时,何时适合使用名称修饰?

示例代码

class Parent():
    def __init__(self, value: int) -> None: 
        self.__value = value

    def how_parent_feels(self) -> None:
        print(self.__value)

class PositiveChild(Parent):
    def __init__(self, value: int) -> None:
        super().__init__(value)
    
    def how_child_feels(self) -> None:
        print(abs(self.__value))

class NegativeChild(Parent): 
    def __init__(self, value: int) -> None:
        super().__init__(value)
    
    def how_child_feels(self) -> None:
        print(abs(self.__value) * -1)

if __name__ == "__main__":
    val = 10
    mom = Parent(val)
    mom.how_parent_feels()
    # >>> 10
    kid1 = PositiveChild(val)
    kid2 = NegativeChild(val)
    kid1.how_parent_feels()
    # >>> 10
    kid2.how_parent_feels()
    # >>> 10
    kid1.how_child_feels()
    # >>> AttributeError: 'PositiveChild' object has no attribute '_PositiveChild__value'
    kid2.how_child_feels()
    # >>> AttributeError: 'NegativeChild' object has no attribute '_NegativeChild__value'

我理解名称修饰使子类拥有_Parent__value属性,父类方法可正常调用,但子类方法期望_PositiveChild__value等属性导致报错。请问如何在子类专属方法中复用父类的名称修饰属性?这是否属于“受保护”属性的误用应完全避免?


问题解答

1. 报错原因

Python的双下划线名称修饰本质是名称改写,而非真正的私有/受保护机制:

  • 父类中定义的self.__value会被Python自动改写为self._Parent__value
  • 子类中写的self.__value会被改写为self._PositiveChild__value(对应PositiveChild)
  • 子类实例中实际存储的是父类改写后的_Parent__value,因此子类找不到自己改写后的属性,触发AttributeError

2. 子类复用父类名称修饰属性的方案

有几种可行方式,但推荐程度不同:

  • 不推荐:直接访问改写后的属性
    可以在子类中直接写self._Parent__value来获取父类的属性,但这完全违背了名称修饰的设计初衷,破坏了封装性。
  • 推荐:父类提供访问接口
    在父类中添加getter方法,或者将属性改为单下划线(Python约定的“受保护”属性):
    # 方案A:添加getter方法
    class Parent():
        def __init__(self, value: int) -> None: 
            self.__value = value
        
        def get_value(self) -> int:
            return self.__value
    
        def how_parent_feels(self) -> None:
            print(self.__value)
    
    class PositiveChild(Parent):
        def how_child_feels(self) -> None:
            print(abs(self.get_value()))
    
    # 方案B:改用单下划线属性(社区惯例的受保护属性)
    class Parent():
        def __init__(self, value: int) -> None: 
            self._value = value  # 单下划线表示内部属性,子类可访问
    
        def how_parent_feels(self) -> None:
            print(self._value)
    
    class PositiveChild(Parent):
        def how_child_feels(self) -> None:
            print(abs(self._value))
    

3. 名称修饰的正确使用场景

双下划线名称修饰的核心用途是避免子类意外覆盖父类的内部属性/方法,而非实现“受保护”访问:

  • 当父类有一个核心内部状态,你不希望子类定义同名属性破坏父类逻辑时,使用双下划线。比如父类有__internal_state,子类即使定义__internal_state,两者会被改写为不同名称,互相隔离。
  • 如果你需要让子类访问父类的内部属性,应该使用单下划线的约定,而非双下划线。

4. 是否属于误用?

你的场景确实属于误用:双下划线不是用来实现“子类可访问的受保护属性”的,它的设计目标是隔离父子类的命名空间。如果需要子类能访问父类的内部属性,应该遵循Python社区惯例,使用单下划线_value,而非双下划线。


内容的提问来源于stack exchange,提问作者Joshua Mincer

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 12:22:20