Python中类属性为字典时新实例未重置的原因探究
类属性中可变与不可变对象的行为差异解释
示例结果回顾
- 第一个示例输出:
1 - 第二个示例输出:
3
原因解析
第一个示例(不可变类属性:整数)
class StatsCourseBuilder(): test = 0 novoA = StatsCourseBuilder() novoA.test += 1 novoA.test += 1 novoB = StatsCourseBuilder() print(novoB.test) # 输出1 novoB.test += 1
整数是不可变类型,当执行novoA.test +=1时,Python无法修改原整数对象的值,会创建一个新的整数对象,并将这个新对象绑定到novoA的实例属性test上。此时novoA的test已经和类属性的test无关,是实例独有的属性。
而novoB没有创建自己的实例属性test,访问的始终是类属性的test=0,执行novoB.test +=1后,实例属性test的值为1,所以打印结果是1。
第二个示例(可变类属性:字典)
class StatsCourseBuilder(): test = {'name' : 0} novoA = StatsCourseBuilder() novoA.test['name'] += 1 novoA.test['name'] += 1 novoB = StatsCourseBuilder() print(novoB.test['name']) # 输出3 novoB.test['name'] += 1
字典是可变类型,当执行novoA.test['name'] +=1时,并没有创建新的字典对象,而是直接在原类属性的字典内部修改name对应的值。因为所有实例共享类属性的可变对象,所以novoA的修改会直接反映到类属性上,novoB访问的还是同一个字典对象。
novoA修改两次后,字典中name的值变为2,novoB再执行一次加1操作,值就变成3,所以打印结果是3。
问题解答
字典作为类属性的值确实是导致该现象的核心原因。本质是可变对象与不可变对象在类属性中的行为差异:
- 不可变类属性:修改操作会触发实例属性的创建,实例不再共享类属性的值
- 可变类属性:原地修改操作会直接改变共享的类属性对象,所有实例都会受影响
参考文档内容(翻译自Python官方文档)
在Python中,类变量是所有类实例共享的属性,而实例变量是每个实例独有的属性。当你尝试修改不可变类型的类变量时,实际上会为当前实例创建一个同名的实例变量,后续对该属性的访问都会指向这个实例变量;而对于可变类型的类变量,由于可以原地修改其内容,所有实例都会共享这个可变对象的修改结果。
内容的提问来源于stack exchange,提问作者José Victor
相关产品推荐
相关产品推荐

