Python类实例共享类字典变量的原因及解决方法
为什么修改一个Student实例的DICT会同步改变所有实例的DICT?
现象成因
嘿,这个问题其实是Python里类变量和实例变量的典型“坑”,我来给你掰扯清楚:
- 你在类级别定义的
DICT = {}是类变量,它属于Student这个类本身,而不是某个具体的实例。所有通过Student类创建的实例,都会共享这同一个字典对象的引用——就好比大家共用一个公共储物柜,谁改里面的东西,所有人打开看到的都是改后的样子。 - 而
NAME虽然在类级别也写了NAME = '',但在__init__方法里你用self.NAME = name给它赋值,这相当于给每个实例创建了独立的实例变量,覆盖了类变量。每个实例的NAME都是自己的专属小盒子,修改自己的不会影响别人的。
用你的代码场景举例:
- 创建
student_one = Student('Leo')时,self.DICT['name'] = name其实是在修改Student类的公共DICT; - 接着创建
student_two = Student('Liz'),同样操作的是那个公共DICT,之前的'Leo'被覆盖成'Liz',所以两个实例打印DICT时都显示{'name': 'Liz'}; - 调用
student_one.change_DICT('Tom')时,还是在修改那个公共DICT,自然所有实例的DICT都会同步变成{'name': 'Tom'}。
最优解决办法(让每个实例有独立的DICT)
要让每个实例拥有自己独立的字典,核心是把DICT定义为实例变量——也就是在__init__方法内部初始化它,而不是在类级别定义。
修改后的代码如下:
class Student(): NAME = '' # 这里的类变量其实也可以移到__init__里,改成实例变量 def __init__(self, name): self.NAME = name # 在这里初始化实例级别的DICT,每个实例都会生成属于自己的新字典 self.DICT = {'name': name} def change_DICT(self, change): self.DICT['name'] = change student_one = Student('Leo') student_two = Student('Liz') print ('Student one NAME: ' + student_one.NAME) print ('Student two NAME: ' + student_two.NAME) print ('---------------------------------') print ('Student one DICT: ' + str(student_one.DICT)) print ('Student two DICT: ' + str(student_two.DICT)) print ('---------------------------------') student_one.change_DICT('Tom') print ('Student one DICT: ' + str(student_one.DICT)) print ('Student two DICT: ' + str(student_two.DICT))
运行结果会变成:
Student one NAME: Leo Student two NAME: Liz --------------------------------- Student one DICT: {'name': 'Leo'} Student two DICT: {'name': 'Liz'} --------------------------------- Student one DICT: {'name': 'Tom'} Student two DICT: {'name': 'Liz'}
这样每个实例的DICT就是独立的了,修改其中一个完全不会影响其他实例。如果之后遇到更复杂的场景(比如需要基于类变量的副本创建实例变量),可以用浅拷贝/深拷贝,但对于当前需求,直接在__init__里初始化新字典是最简单高效的方式。
内容的提问来源于stack exchange,提问作者thithien
相关产品推荐
相关产品推荐

