python类本质是命名空间与属性集合的语法糖,非强制封装容器;实例属性需在__init__中显式初始化,类属性可变对象易致数据污染;super()按mro调用而非直调父类;__getattribute__慎用以防递归。

Python 的 class 不是 Java/C++ 那种“强制封装容器”
Python 的 class 本质是命名空间 + 属性集合的语法糖,不是类型系统的铁壁。它不阻止你动态增删属性、绕过 __init__、甚至把方法当普通函数调用。
- 常见错误现象:
AttributeError: 'A' object has no attribute 'x'出现时,往往不是“类没定义”,而是实例没被正确初始化(比如忘了self.x = x或压根没调用父类super().__init__()) - 使用场景:适合组织相关数据和行为,但别指望靠
class拦住误用——真正约束靠文档、类型提示(typing)、测试,而不是语法 - 参数差异:
__init__是实例创建后才执行的“配置钩子”,不是构造器;__new__才负责返回实例对象,极少需要重写 - 性能影响:纯 Python 类实例比 dict 稍重(有
__dict__、__weakref__等开销),高频小对象可考虑__slots__或namedtuple/dataclass(frozen=True)
实例属性、类属性、装饰器方法三者混用极易出错
Python 不区分“静态字段”和“实例字段”的语法,全靠赋值位置和访问方式决定行为,这是最常踩的坑源头。
- 常见错误现象:
list类属性被所有实例共享导致数据污染,例如items = []写在 class 下,结果多个实例调用.add()后互相看到对方数据 - 使用场景:类属性适合常量(
MAX_RETRY = 3)、缓存(_cache = {})、或需跨实例共享的状态;可变对象必须在__init__中初始化为实例属性 - 装饰器差异:
@property让方法像属性一样读取,但每次调用;@classmethod第一个参数是 class,适合工厂方法;@staticmethod就是普通函数,加它只为逻辑归组,不依赖类或实例 - 兼容性注意:
@property不能直接赋值,除非定义了setter;试图给只读 property 赋值会抛AttributeError
继承中 super() 不是“调父类方法”,而是按 MRO 调下一个
Python 多重继承真实走的是 C3 线性化顺序,super() 返回的是 MRO 中当前类之后的**第一个可匹配项**,不是字面意义的“父类”。
这本书给出了一份关于python这门优美语言的精要的参考。作者通过一个完整而清晰的入门指引将你带入python的乐园,随后在语法、类型和对象、运算符与表达式、控制流函数与函数编程、类及面向对象编程、模块和包、输入输出、执行环境等多方面给出了详尽的讲解。如果你想加入 python的世界,David M beazley的这本书可不要错过哦。 (封面是最新英文版的,中文版貌似只译到第二版)
- 常见错误现象:多层继承下漏掉
super().__init__(),导致某层初始化完全跳过;或在 mixin 中盲目调super().foo(),却不知道下一个是谁,引发TypeError或静默失效 - 使用场景:只要类参与多重继承(哪怕只是继承
object),就该用super();单继承也建议统一用,避免未来扩展时重构成本高 - 验证方式:打印
A.__mro__看顺序,比如class C(A, B): pass的 MRO 是(C, A, B, object),super()在A.__init__中指向B,不是object - 参数传递:所有参与链式调用的方法签名必须一致(至少兼容),否则
super().xxx()可能因参数不匹配崩溃
__getattr__ 和 __getattribute__ 容易引发无限递归
这两个魔术方法控制属性访问,但触发时机和使用边界极细——稍不留神就会自己调自己,直接栈溢出。
立即学习“Python免费学习笔记(深入)”;
- 常见错误现象:
RecursionError: maximum recursion depth exceeded,通常是因为在__getattribute__里又访问了任意实例属性(包括self.__dict__)而没走object.__getattribute__ - 使用场景:
__getattribute__拦所有属性访问,开销大,慎用;__getattr__只在属性找不到时触发,适合实现 fallback 行为(如代理、懒加载) - 安全写法:
__getattribute__中想读属性,必须用object.__getattribute__(self, name);__getattr__中可自由访问其他属性,但别再触发自身 - 调试技巧:加计数器或日志,先 print(name),再判断是否进错分支;上线前务必测
hasattr、getattr、点号访问三种路径









