当前位置: 首页 > news >正文

类命名空间中“同名成员的覆盖规则”和“属性查找时的递归陷阱”


class Student:score = 100  # 类属性(与方法同名)def score(self):  # 方法(与类属性同名)return self.score  # 这里的score  指的是score方法吗?是不是因为score方法把类属性score覆盖了?# 访问类属性:
print(Student.score)  # 后定义的方法覆盖了类属性,输出:<function Student.score at 0x...>
print(Student().score()) # <bound method Student.score of <__main__.Student object at 0x000002AA16B16E40>>

以上代码涉及类命名空间中“同名成员的覆盖规则”和“属性查找时的递归陷阱”,我们一步步拆解:

一、类中同名的类属性和方法:后定义的会覆盖先定义的

在类的命名空间中,后定义的成员会覆盖先定义的同名成员
在你的代码中:

class Student:score = 100  # 1. 先定义类属性 score(值为100)def score(self):  # 2. 后定义方法 score(与类属性同名)return self.score  # 这里的 self.score 指向什么?

当类定义执行时,先将 score = 100 存入类的命名空间;随后定义 def score(self): ... 时,会用新的 score(方法对象)覆盖之前的类属性 score(100)。

因此,类 Student 的命名空间中,score 最终指向的是方法,而非最初的类属性。这就是为什么 print(Student.score) 输出的是 <function Student.score at ...>(方法对象)。

二、方法内部的 self.score 指的是什么?

方法 score(self) 中的 self.score,遵循“实例属性优先于类属性”的查找规则:

  1. 首先查找实例自身的命名空间(self.__dict__),如果实例没有 score 属性,则继续查找类的命名空间。
  2. 由于类的命名空间中,score 已经被方法覆盖(即 Student.score 是方法),因此 self.score 会指向类中的 score 方法(因为实例没有定义 score 属性)。

三、Student().score() 为什么会出问题?

当你执行 Student().score() 时,实际发生了以下过程:

  1. Student() 创建一个实例(假设为 obj),实例的命名空间中没有 score 属性。
  2. obj.score() 调用类中的 score 方法(因为 obj.score 查找到类的 score 方法)。
  3. 方法内部执行 return self.score,这里的 self.score 依然指向类的 score 方法(因为实例仍无 score 属性)。
  4. 因此,return self.score 实际返回的是方法对象本身,而 obj.score() 最终返回的是 <bound method Student.score of ...>(方法的绑定实例形式)。

更严重的是:如果方法内部写成 return self.score()(加括号调用),会导致无限递归

def score(self):return self.score()  # 调用自身,无限递归 → 栈溢出错误

总结

  1. 类中同名的成员(类属性和方法),后定义的会覆盖先定义的,因此 Student.score 最终指向方法。
  2. 方法内部的 self.score 由于实例无此属性,会找到类中被覆盖后的 score 方法(即自身)。
  3. Student().score() 本质是调用方法,而方法返回自身(未加括号时),或因递归调用报错(加括号时)。

这种“类属性与方法同名”的写法会导致逻辑混乱和潜在错误,是 Python 中强烈不推荐的做法。实际开发中应严格避免同名,确保命名空间清晰。

http://www.jsqmd.com/news/27798/

相关文章:

  • 2025年旋转接头标杆厂家最新推荐:多通路旋转接头/水用旋转接头/回转旋转接头/H型旋转接头/液压旋转接头/旭康机械,定义工程机械与工业传热领域可靠性新标准
  • mysql主从配置(保姆级) - 指南
  • 打开浏览器
  • 印度实时股票数据源接口对接文档-IPO新股、k线数据
  • 尝试从源头理解 SVD 原理和计算
  • activemqCVE-2016-3088漏洞复现
  • FortiGuard实验室互联网服务安全技术解析
  • 神舟二十一号|2030年前实现中国人登陆月球的目标不动摇
  • 博客园打印 - miao
  • Python文件操作(下)_ 会写文件,程序便有了记忆
  • Python文件操作(上)_ 会读文件,程序便有了眼睛
  • KeyShot许可管理监控工具使用指南
  • 精益装配,智造未来:哲讯科技SAP解决方案赋能装配制造企业数字化转型
  • 2025 年工业陶瓷源头厂家最新推荐榜:聚焦技术与服务优选,助力企业精准采购优质工业陶瓷产品工业陶瓷/工业陶瓷管公司推荐
  • 2025 年氧化铝陶瓷源头厂家最新推荐排行榜:聚焦六大优质企业,助力下游企业精准选合作方氧化铝陶瓷管/氧化铝陶瓷棒/氧化铝陶瓷片公司推荐
  • revit api视图
  • Oracle ADG 日常巡检指南
  • Ansys Electro-Thermal Analysis
  • Oracle AWR 报告指标全解析:深入理解数据库性能优化的关键
  • Oracle 数据库 dblink 使用全解析
  • 一个白噪声+滤波器demo
  • docker compose 安装 neo4j
  • Oracle数据库七种闪回技术详解与实践示例
  • 分享一个Oracle表空间自动扩容与清理脚本
  • 精密封装,“芯”系未来:哲讯科技SAP解决方案引领芯片封装产业智造升级
  • 2025年市场上卷饼机厂家排行榜:权威推荐与选择指南
  • 2025年市场上​ 烤鸭饼机工厂推荐榜:揭秘行业领先的烤鸭饼机制造商选择指南
  • 2025年市场上烙馍机生产厂家推荐:深度解析领先企业与技术创新
  • 关于taichislam生成拓扑图过于密集
  • Python文件路径 _ 文件在哪里,代码咋知道