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

为何子类Square的私有实例变量前缀仍为_Rectangle?

问题:Square实例的私有属性前缀为何是_Rectangle而非_Square?

我定义了Rectangle类及其子类Square,将所有属性以双下划线开头声明为私有属性。但通过__dict__查看实例属性时发现,Rectangle实例与Square实例的私有属性前缀均为_Rectangle(例如均为_Rectangle__width),而非Square实例预期的_Square__width。我怀疑这与使用super()初始化Square类有关,以下是我的代码及测试结果:

class Rectangle(Base):
    def __init__(self, width, height, x=0, y=0, id=None):
        super().__init__(id)
        self.__width = width
        self.__height = height
        self.__x = x
        self.__y = y

    def to_dictionary(self):
        return self.__dict__

class Square(Rectangle):
    def __init__(self, size, x=0, y=0, id=None):
        super().__init__(size, size, x, y, id)

    def to_dictionary(self):
        return self.__dict__

测试代码:

r2 = Rectangle(5, 5, 5, 5)
rectangle_dict = r2.to_dictionary()
print(rectangle_dict)

s2 = Square(4, 4, 4)
square_dict = s2.to_dictionary()
print(square_dict)

测试结果:

{'id': 1, '_Rectangle__width': 5, '_Rectangle__height': 5, '_Rectangle__x': 5, '_Rectangle__y': 5}
{'id': 2, '_Rectangle__width': 4, '_Rectangle__height': 4, '_Rectangle__x': 4, '_Rectangle__y': 4}

我知道Square类中的to_dictionary方法可继承自Rectangle类,无需重新定义,但结果一致。


原因解释

Python中双下划线开头的私有属性会触发名称改写(Name Mangling),但这个改写规则的核心是:属性的改写前缀由定义该属性的类决定,而非实例所属的类。

你的代码里,__width、__height、__x、__y这些属性都是在Rectangle类的__init__方法中赋值的,所以Python会自动把这些属性名改写为_Rectangle__width这类格式——不管是Rectangle实例还是它的子类Square实例,只要是通过Rectangle的__init__初始化的这些属性,都会带上_Rectangle的前缀。

Square类的__init__只是调用了父类的初始化方法,并没有在自己的类定义里给这些私有属性赋值,所以自然不会生成_Square__xxx格式的属性。如果要让Square拥有自己的私有属性,需要在Square的__init__中单独定义,比如:

class Square(Rectangle):
    def __init__(self, size, x=0, y=0, id=None):
        super().__init__(size, size, x, y, id)
        self.__size = size  # 这个属性会被改写为_Square__size

此时查看Square实例的__dict__,就能看到_Square__size这个属性了。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 22:43:20