Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 附加到defaultdict中的键会产生意外的结果 从集合导入defaultdict phn_字典={“实际”:[],“预测”:[]} phn_dict=defaultdict(lambda:phn_字典) phn_dict[“qwe”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'qwe':{'actual':[123456],'predicted':[]}) phn_dict[“asd”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'asd':{'actual':[123456123456],'predicted':[]}, 'qwe':{'actual':[123456123456],'predicted':[]})_Python_Python 3.x_Defaultdict - Fatal编程技术网

Python 附加到defaultdict中的键会产生意外的结果 从集合导入defaultdict phn_字典={“实际”:[],“预测”:[]} phn_dict=defaultdict(lambda:phn_字典) phn_dict[“qwe”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'qwe':{'actual':[123456],'predicted':[]}) phn_dict[“asd”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'asd':{'actual':[123456123456],'predicted':[]}, 'qwe':{'actual':[123456123456],'predicted':[]})

Python 附加到defaultdict中的键会产生意外的结果 从集合导入defaultdict phn_字典={“实际”:[],“预测”:[]} phn_dict=defaultdict(lambda:phn_字典) phn_dict[“qwe”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'qwe':{'actual':[123456],'predicted':[]}) phn_dict[“asd”][“实际”]。扩展([123456]) phn_dict >>>defaultdict(, {'asd':{'actual':[123456123456],'predicted':[]}, 'qwe':{'actual':[123456123456],'predicted':[]}),python,python-3.x,defaultdict,Python,Python 3.x,Defaultdict,我正在运行Python3.6.4 64位。我需要使用defaultdict生成phn_字典作为其默认值,如上面的代码所示。 我事先不知道我将访问的“asd”和“qwe”等键是什么。可以看出,在我扩展到“asd”的行中,asd和qwe的“实际”键都被扩展了。这是一个bug还是我做错了什么?问题是lambda:phn\u dictionary是一个函数,每次调用它时返回phn\u dictionary——完全相同的dictionary对象。因此,最终得到的字典与一串键的值相同。每次通过一个键进行追加

我正在运行Python3.6.4 64位。我需要使用defaultdict生成phn_字典作为其默认值,如上面的代码所示。
我事先不知道我将访问的“asd”和“qwe”等键是什么。可以看出,在我扩展到“asd”的行中,asd和qwe的“实际”键都被扩展了。这是一个bug还是我做错了什么?

问题是
lambda:phn\u dictionary
是一个函数,每次调用它时返回
phn\u dictionary
——完全相同的dictionary对象。因此,最终得到的字典与一串键的值相同。每次通过一个键进行追加时,在所有其他键上都可见

你想要的不是这本词典,而是一本新词典,它从那本词典的副本开始。正如Brendan Abel在一篇评论中指出的那样,您可能需要一份深度副本,不仅仅是一份新的口述,而是一份包含新列表的新口述:

from collections import defaultdict
phn_dictionary = {"actual": [], "predicted": []}
phn_dict = defaultdict(lambda: phn_dictionary)
phn_dict["qwe"]["actual"].extend([123,456])

phn_dict
>>>defaultdict(<function __main__.<lambda>>,
        {'qwe': {'actual': [123, 456], 'predicted': []}})

phn_dict["asd"]["actual"].extend([123,456])
phn_dict
>>>defaultdict(<function __main__.<lambda>>,
        {'asd': {'actual': [123, 456, 123, 456], 'predicted': []},
         'qwe': {'actual': [123, 456, 123, 456], 'predicted': []}})
或者,这可能更清楚(取决于原始列表应始终为空的事实):

或者,如果您不需要
phn_dictionary
除此之外的任何地方,只需使用Brendan的答案并在函数中从头开始创建dict:

phn_dict = defaultdict(lambda: {key: [] for key in phn_dictionary})
如果这是一个精简的示例,而实际的dict要大得多,或者是一个变量,等等,很明显,最后的版本将无法工作,但是如果这是实际的代码,那么它是最简单的


还有其他方法可以解决这个问题,其中一些可能更清晰,但这是最适合内联lambda的方法,它似乎符合您的思维方式。

这是因为它们都代表同一个词典。如果您将工厂定义为返回字典文本,它将修复该问题

phn_dict = defaultdict(lambda: {"actual": [], "predicted": []})
这是因为每次调用默认工厂lambda时,它都会返回一个新字典,而不是一次又一次地返回同一个字典

或者,您可以使用


这将复制已定义的字典和所有内部值。

其他答案指出重复使用内部列表的引用

如果对象与错误的键一起使用,除非您确实希望引发
KeyError
,否则您可以使用列表的defaultdict中的defaultdict:

phn_dict = defaultdict(lambda: copy.deepcopy(phn_dictionary))
结果:

from collections import defaultdict
phn_dict = defaultdict(lambda: defaultdict(list))
phn_dict["qwe"]["actual"].extend([123,456])
phn_dict["qwe"]["predicted"].extend([768,333])
print(dict(phn_dict)) # clearer repr
{'qwe':defaultdict(,{'actual':[123456],'predicted':[768333]})

这里的默认值不是“看起来像phn\U字典的dict”。默认为
phn\u字典
。谢谢,我将更新question@UsamaArif这不是他所说的措辞。这与可变共享默认值的问题并不完全相同,但明显的混淆是相同的,因此可能有助于理解这种情况。@usamarif不,你不明白,默认值与
phn_字典
相同。请注意,除非您进行深度复制,否则复制的字典中的值列表仍将共享。@BrendanAbel,否,因为克隆时
phn_字典
为空。@Jean-Françoisfare
php_字典
不是空的,而是
{actual:[],“预测”:[]}
是的。我的意思是:列表是空的。但我认为你的答案更清楚。不需要克隆其他人都不使用的变量。@Jean-Françoisfare是的,但复制的词典都引用了相同的空列表。在执行
dict.copy
时不会复制列表。如果在词典中修改列表,将影响相同的结果在所有其他复制的词典中列出。
phn_dict = defaultdict(lambda: copy.deepcopy(phn_dictionary))
from collections import defaultdict
phn_dict = defaultdict(lambda: defaultdict(list))
phn_dict["qwe"]["actual"].extend([123,456])
phn_dict["qwe"]["predicted"].extend([768,333])
print(dict(phn_dict)) # clearer repr
{'qwe': defaultdict(<class 'list'>, {'actual': [123, 456], 'predicted': [768, 333]})}