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

Python派生类中私有属性解析机制及代码执行流程咨询

为什么Tire实例调用area()没有使用_Tire__perimeter?

让我一步步拆解这段代码的执行流程,帮你搞清楚核心问题所在——本质是Python的**名称修饰(Name Mangling)**规则和方法调用时的解析逻辑。

先明确名称修饰的核心规则

Python中,以双下划线__开头的方法/属性,会在类定义的阶段被自动重命名为_类名__方法名的形式。这个重命名是固定的,只和定义该方法的类有关,和调用方法的实例类型无关。

比如:

  • Circle类里的__perimeter,会被重命名为_Circle__perimeter
  • Tire类里的__perimeter,会被重命名为_Tire__perimeter

逐行拆解t = Tire(20); print(t.area())的执行流程

  1. 创建Tire实例t

    • 因为Tire没有重写__init__,所以调用父类Circle的__init__方法,把t.radius设置为20。
  2. 调用t.area()

    • Tire没有重写area方法,所以执行的是Circle类中的area方法。
    • 看Circle的area代码:p = self.__perimeter()——这里的__perimeter在Circle类定义时已经被重命名为_Circle__perimeter,所以这句代码实际等价于p = self._Circle__perimeter()。
    • 此时self是Tire实例,但调用的是_Circle__perimeter(Circle类的私有方法),返回值是2.0 * math.pi * 20 = 40π。
    • 后续计算面积:math.pi * (p *0.5/math.pi)**2 = math.pi * (20)**2 = 400π ≈ 1256.637,这就是你看到的实际结果。
  3. 为什么没用到Tire的__perimeter?

    • Tire类里的_Tire__perimeter只有在Tire类定义的方法中被调用__perimeter时才会触发。比如Tire的perimeter方法里的self.__perimeter(),会被重命名为self._Tire__perimeter(),调用的是Tire自己的私有方法。
    • 但Circle的area方法是在Circle类里定义的,里面的__perimeter已经被绑定到_Circle__perimeter,不管调用它的实例是Circle还是Tire,都会去找_Circle__perimeter方法。

验证:如果重写Tire的area方法会怎样?

如果给Tire添加一个area方法:

class Tire(Circle):
    def perimeter(self):
        return self.__perimeter()
    def __perimeter(self):
        return Circle.perimeter(self)*1.25
    def area(self):
        p = self.__perimeter()
        return math.pi * (p *0.5/math.pi)**2

此时调用t.area(),self.__perimeter()会被重命名为self._Tire__perimeter(),计算出来的面积就是基于50π的结果,和你最初的预期一致。

总结

名称修饰是类定义阶段的静态处理,不是运行时的动态解析。在哪个类里写的__xxx,就会被绑定到_类名__xxx,和调用该方法的实例类型无关。这也是Python私有方法的设计初衷:确保父类的私有方法不会被子类意外覆盖,同时子类也可以拥有自己同名的私有方法,互不干扰。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 06:28:11