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

Python类的dict类属性为何在多个实例间共享数据?

问题原因解答

核心原理:类属性与实例属性的查找、修改逻辑

你遇到的现象是Python类属性与实例属性的差异,加上可变、不可变对象的操作特性共同导致的,和参数传递规则无关,核心是属性的查找与修改逻辑:

  • 访问self.xxx时,Python会优先查找当前实例的私有属性字典__dict__,如果找不到对应key,就会向上查找实例所属类的__dict__,仍找不到则继续沿继承链向上查找。
  • 对不可变对象执行self.xxx = yyy是赋值操作,会直接在当前实例上新增同名实例属性,不会修改类属性;对可变对象执行self.xxx[key] = yyy是原地修改操作,不会新增实例属性,会直接修改找到的属性指向的对象内容。

分属性解释表现

mystr表现符合预期的原因

  1. 你在B类中定义的mystr = 'B'是类属性,类型为不可变的字符串
  2. A类__init__中执行的self.mystr = 'A'是赋值操作,会在当前实例上新增一个名为mystr的实例属性,不会修改B类的类属性mystr
  3. 每个B类实例初始化时,还未执行super().__init__前,实例自身没有mystr属性,所以会读取到B类的类属性值B;执行super后实例有了自己的mystr实例属性值A,下一个新实例初始化时读取的类属性仍为B,符合预期。

mydict表现不符合预期的原因

  1. 你在B类中定义的mydict = {}是类属性,类型为可变的字典
  2. A类__init__中执行的self.mydict['key'] = 'value'是原地修改操作,不是赋值操作:此时实例自身还没有mydict实例属性,所以找到的是B类的类属性mydict,直接修改了这个类属性指向的字典对象的内容
  3. 第一个实例b1初始化完成后,B类的类属性mydict已经被修改为{'key': 'value'},第二个实例b2初始化时,还未执行super前读取self.mydict,同样找不到实例属性,就会读取到已经被修改过的B类类属性,所以输出不是你预期的空字典。

修复方案

如果需要每个实例拥有独立的mydict,不要把mydict定义为类属性,改为在B类的__init__中初始化实例属性即可,修改后代码如下:

class A:
    def __init__(self):
        super().__init__()
        self.mystr = 'A'
        self.mydict['key'] = 'value'

class B(A):
    mystr = 'B'
    def __init__(self, name):
        # 每个实例初始化独立的字典,作为实例属性存在,不共用类属性
        self.mydict = {}
        print(name, 'mystr (before)', self.mystr)
        print(name, 'mydict (before)', self.mydict)
        super().__init__()
        print(name, 'mystr (after)', self.mystr)
        print(name, 'mydict (after)', self.mydict)

if __name__ == '__main__':
    b1 = B('b1')
    b2 = B('b2')

修改后运行时,第二个实例b2初始化前读取的mydict就是独立的空字典,符合预期。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 12:36:03