You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python类属性作用域异常:为何列表与int表现不同?

Python类属性的“共享”陷阱:可变与不可变对象的差异

问题复现

定义类X:

class X():
    a = list()
    b = int
    def __init__(self, value):
        self.a.append(value)
        self.b = value

实例化后:

u = X(0)
v = X(1)

得到结果:

u.a == [0,1]  # 两个实例的a共享了所有值
u.b == 0  
v.a == [0,1]
v.b == 1  # 每个实例的b是独立的

核心原因:可变对象 vs 不可变对象 + 属性赋值逻辑

这和“类型影响作用域”无关,本质是对象的可变性以及你对属性的操作方式不同:

  • 对于a(列表,可变对象):
    类中a = list()定义的是类属性,指向一个可变的列表对象。在__init__里你执行的是self.a.append(value)——这个操作并没有给实例u或v创建自己的a属性,只是通过self.a找到类属性的列表,然后修改它的内容。所有实例访问a时,因为自己没有这个属性,都会去取类属性的同一个列表,所以会看到所有修改后的结果。

  • 对于b(int类型,不可变对象):
    类中b = int是类属性,但在__init__里你执行了self.b = value——这一步是给当前实例创建了一个名为b的实例属性,直接覆盖了对类属性的引用。因为int是不可变对象,每次赋值都是给实例绑定一个新的int对象,所以每个实例的b都是独立的,和类属性无关。

关键总结

  • 当你对属性执行修改对象内容的操作(比如列表的append、字典的update),如果实例没有自己的该属性,会直接修改类属性指向的可变对象,导致所有实例共享变化。
  • 当你对属性执行赋值操作(self.xxx = ...),无论对象是否可变,都会给实例创建自己的属性,之后实例访问该属性时会优先用自己的,不再关联类属性。

如果想让每个实例的a独立,应该在__init__里给实例赋值:

class X():
    def __init__(self, value):
        self.a = [value]  # 每个实例创建自己的列表
        self.b = value

内容的提问来源于stack exchange,提问作者tikitakitok

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 04:17:13