为什么 [defaultdict(int)] * 3 return 三个引用相同 object

Why does [defaultdict(int)] * 3 return three references to the same object

编辑:

为什么 [defaultdict(int)] * 3 return 三个引用同一个 object?

原标题

Unpack list of defaultdicts into variables has unexpected behavior in Python

defaultdict 类型的初始化列表解包到变量中似乎没有按我预期的方式工作。有谁知道为什么会这样(请参阅下面的代码片段)?我正在使用 Python 3.9.1.

# Equivalent behavior - works OK
a,b,c = [int(), int(), int()]
d,e,f = [int()] * 3

# Expected equivalent behavior - BEHAVES DIFFERENTLY
l,m,p = [defaultdict(int), defaultdict(int), defaultdict(int)]
q,r,s = [defaultdict(int)] * 3

完整片段:

>>> a,b,c = [int(), int(), int()]
>>> a+=4; b+=2; c+=7
>>> a,b,c
(4, 2, 7)
>>> d,e,f = [int()] * 3
>>> d+=11; e+=8; f+= 41
>>> d,e,f
(11, 8, 41)

>>> from collections import defaultdict
>>> l,m,p = [defaultdict(int), defaultdict(int), defaultdict(int)]
>>> l['a']+=1; m['b']+=2; m['c']+=3;
>>> l,m,p
(
  defaultdict(<class 'int'>, {'a': 1}), 
  defaultdict(<class 'int'>, {'b': 2, 'c': 3}), 
  defaultdict(<class 'int'>, {})
)
>>> q,r,s = [defaultdict(int)] * 3
>>> q['a']+=111; r['b']+=222; m['c']+=333;
>>> q,r,s
(
  defaultdict(<class 'int'>, {'a': 111, 'b': 222}), 
  defaultdict(<class 'int'>, {'a': 111, 'b': 222}), 
  defaultdict(<class 'int'>, {'a': 111, 'b': 222})
)

此问题基于问题 提出的主题。

问题与内存中的位置有关。一个简单的控制台测试表明:

> from collections import defaultdict
> l,m,p = [defaultdict(int), defaultdict(int), defaultdict(int)]
> id(l) == id(p)
False
> id(m) == id(p)
False

现在我们换个方式试试:

> l,m,p = [defaultdict(int)] * 3
> id(l) == id(p)
True
> id(m) == id(p)
True

在第一种情况下,您在内存中创建了三个独立的槽。第二,你在内存中创建一个点,然后创建两个额外的指针指向内存中的那个槽;因此当你更新一个时,它们都会改变,因为它们都指向内存中的同一个插槽。

更详细地说明了为什么某些数据类型会发生这种情况,而其他数据类型不会。 TL;DR - 小整数可以在同一个对象中,但为了优化而使用不同的指针。这就是为什么您可以 运行 id()is 检查整数变量并查看它们指向同一个对象,但在修改每个对象时让它们独立运行。