如果值是多个数组,则使用键将值附加到python字典值

时间:2019-11-12 06:05:04

标签: python dictionary

我声明了一个Python字典,其中的键和值是多个数组。是否可以使用键和值索引附加数组?

这是我初始化python字典cvfoldacc的方式

a = []
b = [] 
c = [] 
d = [] 
e = [] 
f = []
classifiers = [a,b,c,d,e,f]
cvfoldacc = dict.fromkeys(range(2,11), classifiers) 

此初始化的结果如下:

cvfoldacc>>

{2: [[], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

当我尝试将key(2)的第一个列表附加到代码中时 cvfoldacc [2] [0] .append(8),我得到的结果是:

{2: [[8], [], [], [], [], []],
 3: [[8], [], [], [], [], []],
 4: [[8], [], [], [], [], []],
 5: [[8], [], [], [], [], []],
 6: [[8], [], [], [], [], []],
 7: [[8], [], [], [], [], []],
 8: [[8], [], [], [], [], []],
 9: [[8], [], [], [], [], []],
 10: [[8], [], [], [], [], []]}

但是预期的答案应该是这样:

{2: [[8], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

2 个答案:

答案 0 :(得分:2)

这是旧的deep copyshallow copy之类的东西。 试试这个:

>>> a = []
>>> b = [] 
>>> c = [] 
>>> d = [] 
>>> e = [] 
>>> f = []
>>> classifiers = [a,b,c,d,e,f]
>>> import copy
>>> cvfoldacc = {k:copy.deepcopy(classifiers) for k in range(2,11)}
>>> cvfoldacc[2][0].append(8)
>>> cvfoldacc 
{2: [[8], [], [], [], [], []],
 3: [[], [], [], [], [], []],
 4: [[], [], [], [], [], []],
 5: [[], [], [], [], [], []],
 6: [[], [], [], [], [], []],
 7: [[], [], [], [], [], []],
 8: [[], [], [], [], [], []],
 9: [[], [], [], [], [], []],
 10: [[], [], [], [], [], []]}

您正在做

a = []
b = [] 
c = [] 
d = [] 
e = [] 
f = []
classifiers = [a,b,c,d,e,f]
cvfoldacc = dict.fromkeys(range(2,11), classifiers) 

现在,要创建的字典在每个键中都有相同的列表,不仅它们看起来相同,而且是完全相同的对象,具有相同的identity(在CPython中的内存位置)。让我们看看:

>>> id(cvfoldacc[2])
171760008
>>> id(cvfoldacc[3])
171760008

这些对于其他值也将相同。 因此dict.fromkeys()为字典中的所有键分配相同的值,而不创建它的副本。

现在,以另一种方式,在您进行浅表复制时,此问题将得到解决:

>>> cvfoldacc = {a:classifiers.copy() for a in range(2,11)}
>>> id(cvfoldacc[2])
171840616
>>> id(cvfoldacc[3])
171847688

解决正确了吗?

>>> cvfoldacc[2][0].append(8)
{2: [[8], [], [], [], [], []],
 3: [[8], [], [], [], [], []],
 4: [[8], [], [], [], [], []],
 5: [[8], [], [], [], [], []],
 6: [[8], [], [], [], [], []],
 7: [[8], [], [], [], [], []],
 8: [[8], [], [], [], [], []],
 9: [[8], [], [], [], [], []],
 10: [[8], [], [], [], [], []]}

显然不是!现在让我们看起来更深。让我们看一下列表中列表的id

>>> id(cvfoldacc[2][0])
171810120
>>> id(cvfoldacc[3][0])
171810120

因此,即使list.copy()创建了外部列表的副本,内部列表也是相同的。因此,基本上,您要追加list: a中存在的keys,以便对所有内容进行修改。

Deepcopy递归复制所有对象,从而避免了该问题。

答案 1 :(得分:1)

您需要为每个list之类的值创建新的key

>>> a = []
>>> b = [] 
>>> c = [] 
>>> d = [] 
>>> e = [] 
>>> f = []
>>> classifiers = [a,b,c,d,e,f] 
>>> 
>>> d = {k:[x[:] for x in classifiers] for k in range(2,11)} # note i am creating a copy using the `list[:]` notation.
# either the comprehension or `k: copy.deepcopy(classifiers)` is fine
>>> d
{2: [[], [], [], [], [], []], 3: [[], [], [], [], [], []], 4: [[], [], [], [], [], []], 5: [[], [], [], [], [], []], 6: [[], [], [], [], [], []], 7: [[], [], [], [], [], []], 8: [[], [], [], [], [], []], 9: [[], [], [], [], [], []], 10: [[], [], [], [], [], []]}
>>> d[2][0].append(1)
>>> d
{2: [[1], [], [], [], [], []], 3: [[], [], [], [], [], []], 4: [[], [], [], [], [], []], 5: [[], [], [], [], [], []], 6: [[], [], [], [], [], []], 7: [[], [], [], [], [], []], 8: [[], [], [], [], [], []], 9: [[], [], [], [], [], []], 10: [[], [], [], [], [], []]}