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

子类继承的类方法访问私有类变量的问题

子类继承的类方法访问私有类变量的问题

我完全懂你的困惑,咱们先拆解一下为什么会出现这个结果,再一步步解决问题。

首先得搞清楚Python里双下划线私有变量的机制:Python会对以双下划线开头的变量做「名字修饰(name mangling)」——简单说就是解释器会自动把__x改成_类名__x的形式。所以你代码里:

  • 父类Foo的__x实际会变成_Foo__x
  • 子类Goo的__x实际会变成_Goo__x

而你在父类Foo里写的get_x方法,return cls.__x经过名字修饰后,其实是在找_Foo__x。哪怕你用子类Goo的实例调用这个方法,它本质还是父类的方法,只会去拿_Foo__x的值(也就是1),这就是为什么g.get_x()返回1。而y是公共变量,子类的y会直接覆盖父类的,所以get_y能拿到4。

接下来给你几个可行的解决方案,按推荐程度排序:

方案一:改用单下划线的「保护变量」(最推荐)

这是Python社区约定俗成的写法:单下划线开头的变量表示「仅供内部使用」,不会被名字修饰,子类可以正常覆盖。修改代码如下:

class Foo:
    _x = 1
    y = 2

    @classmethod
    def get_x(cls):
        return cls._x

    @classmethod
    def get_y(cls):
        return cls.y

class Goo(Foo):
    _x = 3
    y = 4

g = Goo()
print("x=%d" % g.get_x())  # 输出 x=3
print("y=%d" % g.get_y())  # 输出 y=4

这种方法既符合Python编码规范,又能轻松实现子类覆盖父类变量的需求,是最优解。

方案二:在子类中重写get_x方法

如果你一定要保留双下划线的私有变量,可以在子类里重写get_x方法,让它返回子类自己的私有变量:

class Foo:
    __x = 1
    y = 2

    @classmethod
    def get_x(cls):
        return cls.__x

    @classmethod
    def get_y(cls):
        return cls.y

class Goo(Foo):
    __x = 3
    y = 4

    @classmethod
    def get_x(cls):
        return cls.__x

g = Goo()
print("x=%d" % g.get_x())  # 输出 x=3
print("y=%d" % g.get_y())  # 输出 y=4

不过这种方法有点冗余,每个子类都得重写一遍get_x,适合特殊场景下使用。

方案三:利用名字修饰规则手动获取(不推荐)

你也可以通过getattr结合类名,手动拼接出修饰后的变量名来获取值,但这种方法破坏了私有变量的封装性,可读性也差,不建议使用:

class Foo:
    __x = 1
    y = 2

    @classmethod
    def get_x(cls):
        # 手动拼接修饰后的变量名
        return getattr(cls, f"_{cls.__name__}__x")

    @classmethod
    def get_y(cls):
        return cls.y

class Goo(Foo):
    __x = 3
    y = 4

g = Goo()
print("x=%d" % g.get_x())  # 输出 x=3
print("y=%d" % g.get_y())  # 输出 y=4

总结一下,优先选方案一,既简洁又符合规范。

备注:内容来源于stack exchange,提问作者AS Han

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.21 08:55:29