来自dict.fromkeys的不需要的行为

Ant*_*rre 20 python

我想使用初始化集合的字典(在Python 2.6中)dict.fromkeys,但结果结构表现奇怪.进一步来说:

>>>> x = {}.fromkeys(range(10), set([]))
>>>> x
{0: set([]), 1: set([]), 2: set([]), 3: set([]), 4: set([]), 5: set([]), 6: set([]), 7: set([]), 8: set([]), 9: set([])}
>>>> x[5].add(3)
>>>> x
{0: set([3]), 1: set([3]), 2: set([3]), 3: set([3]), 4: set([3]), 5: set([3]), 6: set([3]), 7: set([3]), 8: set([3]), 9: set([3])}
Run Code Online (Sandbox Code Playgroud)

我显然不想在所有集合中添加3,仅添加到对应的集合x[5].当然,我可以通过初始化避免问题x没有fromkeys,但我想了解我在这里失踪.

Der*_*ter 16

您可以使用生成器表达式执行此操作:

x = dict( (i,set()) for i in range(10) )
Run Code Online (Sandbox Code Playgroud)

在Python 3中,您可以使用字典理解:

x = { i : set() for i in range(10) }
Run Code Online (Sandbox Code Playgroud)

在这两种情况下,set()都会为每个元素计算表达式,而不是对其进行一次计算并复制到每个元素.

  • +1即使在接受的答案解释得很好之后也提供了解决方案。 (2认同)

Gly*_*yph 15

第二个参数dict.fromkeys只是一个值.您创建了一个字典,其设置与每个键的值相同.大概你了解它的工作方式:

>>> a = set()
>>> b = a
>>> b.add(1)
>>> b
set([1])
>>> a
set([1])
Run Code Online (Sandbox Code Playgroud)

你在那里看到了同样的行为; 你的情况,x[0],x[1],x[2](等)的访问完全相同的所有不同的方式set对象.

使用其字符串表示包含其内存地址的对象更容易看到,您可以看到它们是相同的:

>>> dict.fromkeys(range(2), object())
{0: <object object at 0x1001da080>,
 1: <object object at 0x1001da080>}
Run Code Online (Sandbox Code Playgroud)