在python中将值赋给字典会导致值在错误的键中

在python中将值赋给字典会导致值在错误的键中,python,dictionary,Python,Dictionary,我正在编程,我遇到了一个奇怪的问题。我想找到所有可能的方法从两个自然数生成一个(自然)数。我创建了一个简单的循环,我注意到了奇怪的结果。例如,1由3和1生成。一些调查结果如下: #Importing stuff I often use in my solutions/tests from math import sqrt, log, floor, pow, fabs, factorial from sets import Set from random import randint from i

我正在编程,我遇到了一个奇怪的问题。我想找到所有可能的方法从两个自然数生成一个(自然)数。我创建了一个简单的循环,我注意到了奇怪的结果。例如,1由3和1生成。一些调查结果如下:

#Importing stuff I often use in my solutions/tests
from math import sqrt, log, floor, pow, fabs, factorial
from sets import Set
from random import randint
from itertools import permutations
import sys


dub = dict()

c = 0 #Counting the number of elements in dub[18], use to track changes
for i in range (1,10):
    if 18 in dub: #setting c = len(dub[18])
        c = len(dub[18])
    for j in range (i+1,10):
        pair = [[i,j]]
        v = i+j
        if v in dub:
            dub[v].append(pair[0])
        else:
            dub[v] = pair
        v = i*j        
        if v in dub:
            dub[v].append(pair[0])
        else:
            if i == 3 and j == 8: print 'here', v # The value that is added to dub[18] instead of dub[24]
            dub[v] = pair
        if 18 in dub and not c == len(dub[18]): #This is how I found that something is wrong.
            c = len(dub[18])
            print dub[18]
            print v,i,j
            raw_input()
[[2, 9]]
18 2 9

[[2, 9], [3, 6]]
18 3 6

here 24
[[2, 9], [3, 6], [3, 8]]
24 3 8
结果是:

#Importing stuff I often use in my solutions/tests
from math import sqrt, log, floor, pow, fabs, factorial
from sets import Set
from random import randint
from itertools import permutations
import sys


dub = dict()

c = 0 #Counting the number of elements in dub[18], use to track changes
for i in range (1,10):
    if 18 in dub: #setting c = len(dub[18])
        c = len(dub[18])
    for j in range (i+1,10):
        pair = [[i,j]]
        v = i+j
        if v in dub:
            dub[v].append(pair[0])
        else:
            dub[v] = pair
        v = i*j        
        if v in dub:
            dub[v].append(pair[0])
        else:
            if i == 3 and j == 8: print 'here', v # The value that is added to dub[18] instead of dub[24]
            dub[v] = pair
        if 18 in dub and not c == len(dub[18]): #This is how I found that something is wrong.
            c = len(dub[18])
            print dub[18]
            print v,i,j
            raw_input()
[[2, 9]]
18 2 9

[[2, 9], [3, 6]]
18 3 6

here 24
[[2, 9], [3, 6], [3, 8]]
24 3 8

我应该使用的键是24,但列表放在键18下。为什么会这样?

您正在对多个键重复使用相同的列表。线路

pair = [[i,j]]
创建包含单个对的列表。此列表用于
else
分支

else:
    dub[v] = pair
使用相同的列表对象生成两个不同的键。因为它是同一个对象,所以这两个键中任何键的列表附件都可以在另一个键中看到

编辑:下面是一个演示此行为的简单示例:

>>> d = {}
>>> a = []
>>> d[0] = a
>>> d[1] = a
>>> d[0].append(2)
>>> d[0]
[2]
>>> d[1]
[2]
显而易见的解决办法是只将该对分配给名称
,并在需要时创建包含该对的新列表:

dub = {}
for i in range (1, 10):
    for j in range (i + 1, 10):
        pair = [i, j]
        v = i + j
        if v in dub:
            dub[v].append(pair)
        else:
            dub[v] = [pair]
        v = i * j
        if v in dub:
            dub[v].append(pair)
        else:
            dub[v] = [pair]
为了进一步简化此代码,您可以将
if
s替换为
dict.setdefault()


如果您使用按键中的
,也会导致此问题

data=dict.fromkeys([int(x)表示第[1:][]行中的x,[]))

解决方案是使用
setdefault
而不是
fromkeys
来启动字典的默认值:

data.setdefault(idx,[]).append((行[0],val))


你的解决方案行得通,但我还是不明白。我使用不同的键,但我附加到同一个列表中?@Yotam:我添加了一个很有希望的解释性示例。@SvenMarmach:谢谢。我现在明白了。