在子类中修改类变量的核心逻辑是:区分 “修改父类的类变量” 和 “重写 / 修改子类自己的类变量”—— 子类可以独立维护自己的类变量,也能主动修改父类的类变量,两种场景的写法和效果完全不同,下面分场景讲透具体操作、避坑点和应用场景。
一、先明确核心前提
子类继承父类后,会 “共享” 父类的类变量(子类未重写时,访问子类 / 子类实例的类变量,实际读的是父类的);但子类可以通过「子类名。类变量名」创建 / 修改自己的类变量,与父类解耦。
| 操作目标 | 核心写法 | 效果 |
|---|---|---|
| 修改子类自己的类变量 | 子类名.类变量名 = 新值 | 子类有了独立的类变量,不影响父类 |
| 修改父类的类变量 | 父类名.类变量名 = 新值 | 父类及所有未重写该变量的子类同步生效 |
二、场景 1:重写 / 修改子类自己的类变量(最常用)
这是子类定制化类变量的核心方式 —— 子类通过「子类名。类变量名」赋值后,会在子类的命名空间中创建独立的类变量,不再共享父类的同名变量,后续修改子类的该变量也不会影响父类。
步骤 1:子类继承父类(未重写类变量)
此时子类共享父类的类变量:
python
运行
class Parent: # 父类类变量 shared_var = "父类初始值" count = 0 class Child(Parent): # 未重写父类的类变量,默认共享 pass # 验证:子类/子类实例读的是父类的类变量 print(Child.shared_var) # 输出:父类初始值 print(Child().shared_var) # 输出:父类初始值 print(Parent.shared_var) # 输出:父类初始值步骤 2:修改子类自己的类变量(重写 + 修改)
通过「子类名。类变量名」赋值,子类会创建独立的类变量:
python
运行
# 1. 重写:给子类新增独立的类变量 Child.shared_var = "子类重写值" # 验证:子类/子类实例读自己的,父类不变 print(Child.shared_var) # 输出:子类重写值(子类自己的变量) print(Child().shared_var) # 输出:子类重写值 print(Parent.shared_var) # 输出:父类初始值(父类不受影响) # 2. 后续修改子类的类变量(仅影响子类) Child.count = 10 Child.count += 1 print(Child.count) # 输出:11 print(Parent.count) # 输出:0(父类仍不变)场景 1 扩展:在子类的方法中修改子类自己的类变量
在子类的实例方法 / 类方法中,修改子类类变量需用「子类名。类变量名」,而非self(self赋值会创建实例变量):
python
运行
class Child(Parent): # 先定义子类自己的类变量(可选,也可后续赋值) child_count = 0 def add_child_count(self): # 正确:修改子类自己的类变量 Child.child_count += 1 # 验证 c = Child() c.add_child_count() print(Child.child_count) # 输出:1 print(Parent.child_count) # 报错:父类无该变量(解耦)三、场景 2:在子类中修改父类的类变量
如果需要让父类的类变量全局生效(影响父类、其他未重写的子类),可以在子类中通过「父类名。类变量名」直接修改父类的类变量。
示例:子类操作父类的类变量
python
运行
class Parent: total = 0 # 父类类变量:全局计数 class Child1(Parent): def add_parent_total(self): # 子类方法中修改父类的类变量 Parent.total += 1 class Child2(Parent): # 未重写total,共享父类的 pass # 验证:子类修改父类变量,全局生效 c1 = Child1() c1.add_parent_total() print(Parent.total) # 输出:1(父类变了) print(Child1.total) # 输出:1(Child1未重写,共享父类) print(Child2.total) # 输出:1(Child2也共享父类) # 若Child1重写了total,则不再受父类影响 Child1.total = 100 print(Child1.total) # 输出:100(子类自己的变量) print(Parent.total) # 输出:1(父类仍不变)四、场景 3:子类中修改可变类型的类变量(避坑重点)
如果父类的类变量是列表、字典等可变类型,需注意两种操作的差异:
- 修改父类变量的内部元素:通过
父类名.变量名.方法()(如append),会影响所有共享该变量的子类; - 给子类赋值新的可变对象:通过
子类名.变量名 = 新对象,子类创建独立的类变量,与父类解耦。
示例:可变类型类变量的修改
python
运行
class Parent: # 父类可变类变量(列表) items = [1, 2, 3] class Child(Parent): pass # 操作1:子类中修改父类变量的内部元素(全局生效) Parent.items.append(4) print(Parent.items) # 输出:[1,2,3,4] print(Child.items) # 输出:[1,2,3,4](共享父类) # 操作2:子类赋值新的列表(创建子类独立变量) Child.items = [10, 20] print(Child.items) # 输出:[10,20](子类自己的) print(Parent.items) # 输出:[1,2,3,4](父类不变) # 坑点:子类实例赋值可变变量名 → 仅创建实例变量 c = Child() c.items = [100] print(c.items) # 输出:[100](实例变量) print(Child.items) # 输出:[10,20](子类类变量不变)五、避坑总结:子类修改类变量的 3 条关键规则
- 改子类自己的变量:用
子类名.变量名 = 新值,与父类解耦,不影响父类; - 改父类的变量:用
父类名.变量名 = 新值,会影响所有未重写该变量的子类; - 禁用错误操作:
- 不要用
子类实例.变量名 = 新值(仅创建实例变量,不修改类变量); - 不要在子类方法中用
self.变量名 = 新值(同理,创建实例变量); - 可变类型变量优先用「类名操作」,避免 “实例修改父类变量内部元素” 导致的逻辑混乱。
- 不要用
六、应用场景推荐
| 需求场景 | 推荐操作 |
|---|---|
| 子类定制独有的类变量 | 子类名。变量名 = 新值(重写) |
| 全局修改所有类的共享变量 | 父类名。变量名 = 新值 |
| 子类临时扩展父类可变变量 | 父类名。变量名。方法 ()(如 append) |
| 子类完全独立于父类变量 | 子类名。变量名 = 新的可变对象 |
https://avg.163.com/topic/detail/8014823
https://avg.163.com/topic/detail/8014892
https://avg.163.com/topic/detail/8014932
https://avg.163.com/topic/detail/8015035