Python类中列表行为异常的原因及实现机制咨询
Python中列表与类结合的共享实例问题解析
你观察到的现象本质是可变对象在Python中的特殊处理逻辑,下面分场景拆解实现机制,并说明设计目的:
一、带默认列表参数的构造方法:实例共享列表的原因
Python的函数默认参数是在函数定义阶段就创建完成,而非每次调用函数时重新生成。当你定义def __init__(self, money=[200]):时,[200]这个列表对象在类被加载时就已经固定在内存中。
每次调用BasicClass()(不传参数)时,self.money都会指向这个预先创建好的同一个列表实例。因此两个对象的money属性本质是对同一个列表的引用,调用append方法会直接修改这个共享列表。
你可以通过打印内存地址验证:
print(id(object.money), id(object_2.money)) # 输出两个相同的内存地址
二、类变量版本:实例共享列表的原因
类变量是属于类本身的属性,所有该类的实例在未定义同名实例变量时,访问的都是类级别的同一个对象。
在这个例子中,BasicClass.money是类级别的列表对象,self.money.append(value)并没有给实例创建专属的money属性,而是直接修改了类变量指向的列表。因此所有实例访问self.money时,都会看到这个被修改过的共享列表。
验证代码:
print(id(object.money), id(BasicClass.money)) # 输出相同的内存地址
三、无默认参数版本:实例各自拥有列表的原因
每次创建实例时,你都传入了新的列表[100]——也就是每次调用BasicClass([100])都会生成一个全新的列表对象,self.money指向这个新对象。两个实例的money引用的是不同的列表,修改自然互不影响。
设计目的
- 性能优化:默认参数仅在定义时创建一次,避免了每次调用函数重复创建相同可变对象的开销,节省内存与初始化时间。
- 类变量的语义匹配:类变量的设计初衷就是承载类的共享状态,比如统计实例总数、共享全局配置等,这种共享行为符合“类级共享数据”的语义。
避免共享的正确写法
修复默认参数场景
将默认值设为None,在__init__内动态创建新列表:
class BasicClass: def __init__(self, money=None): self.money = money if money is not None else [200] def add_money(self, value): self.money.append(value)
修复类变量场景
在__init__中创建实例专属的列表变量:
class BasicClass: def __init__(self): self.money = [200] # 每个实例初始化独立列表 def add_money(self, value): self.money.append(value)
内容的提问来源于stack exchange,提问作者mjrmarquis
相关产品推荐
相关产品推荐

