当类属性和实例属性同名时,读取优先实例属性,修改默认操作实例属性;del删除仅影响当前作用域,误用可变类属性会导致实例间共享。

当类属性和实例属性同名时,Python 的读取和修改行为遵循明确的规则:读取时优先使用实例属性(如果存在),修改时默认操作的是实例属性(不会影响类属性),除非显式通过类名操作。
读取时:实例属性覆盖类属性
访问对象属性时,Python 先在实例的 __dict__ 中查找,命中则直接返回;未命中才去类及其父类的 __dict__ 中查找。因此,一旦实例拥有同名属性,类属性就被“遮蔽”(shadowed)。
- 例如:class A: x = 10; a = A(); a.x = 20 → a.x 读取结果为 20(来自实例)
- 而 A.x 仍是 10,不受影响
- 新创建的实例(如 b = A())未设置 x,b.x 读取的是类属性 10
修改时:默认创建或更新实例属性
对实例执行赋值操作(如 obj.attr = value),Python 总是将该属性写入实例的 __dict__,无论类中是否已存在同名类属性。
- a.x = 30 并不会改变 A.x,只是更新了 a.__dict__['x']
- 若想修改类属性本身,必须显式通过类名赋值:A.x = 30
- 注意:修改类属性会影响所有尚未覆盖该属性的实例(即其
__dict__中无该键的实例)
删除行为:只影响当前作用域
使用 del obj.attr 删除的是实例属性;删除后再次访问该属性,会自动回退到类属性(如果存在)。
- del a.x 后,a.x 又变为 A.x 的值(如 10)
- del A.x 则从类中移除该属性,之后所有未定义 x 的实例访问 x 都会触发 AttributeError
- 不能用 del obj.attr 删除类属性——它只作用于实例字典
常见误区与建议
容易误以为给实例赋同名属性是在“修改类属性”,或误用 self.attr = ... 初始化可变类属性(如列表、字典),导致多个实例意外共享同一对象。
- ❌ 错误模式:class B: data = []; def add(self, x): self.data.append(x) → 所有实例共用一个 list
- ✅ 正确做法:在 __init__ 中为每个实例创建独立副本:self.data = []
- ✅ 检查归属:打印 obj.__dict__ 和 type(obj).__dict__ 可直观分辨属性所在位置










