我有一个字典列表,我正在尝试根据列表中其他其他变量的值分配字典键:值对。我想将每个变量列表的“ith”值分配给block_params_list中的第i个字典,并将变量名称(作为字符串)作为键。问题是虽然代码适当地分配了值(如“pprint(item)”所示),但是当整个枚举循环结束时,“block_params_list”中的每个项目都等于最后一个项目的值。
我无法解释这种行为。有人可以帮忙吗?谢谢!
'''empty list of dictionaries'''
block_params_list = [{}] * 5
'''variable lists to go into the dictionaries'''
ran_iti = [False]*2 + [True]*3
iti_len = [1,2,4,8,16]
trial_cnt = [5,10,15,20,25]
'''the loops'''
param_list= ['iti_len','trial_cnt','ran_iti']#key values, also variable names
for i,item in enumerate(block_params_list):
for param in param_list:
item[param] = eval(param)[i]
pprint(item) #check what each item value is after assignment
pprint(block_params_list) #prints a list of dictionaries that are
#only equal to the very last item assigned
答案 0 :(得分:3)
你已经遇到了一个普通的问题'在Python中,在你的第一行代码上:
# Create a list of five empty dictionaries
>>> block_params_list = [{}] * 5
指令[{}] * 5
相当于这样做:
>>> d = {}
>>> [d, d, d, d, d]
该列表包含对同一字典的五个引用。你说" block_params_list'中的每个项目。等于最后一项" - 这是一种幻觉,实际上只有一个项目在" block_params_list"并且你正在分配它,然后查看它,五次通过五个不同的引用。
您需要使用循环来创建列表,以确保创建五个不同的词典:
block_params_list = []
for i in range(5):
block_params_list.append({})
或
block_params_list = [{} for i in range(5)]
NB。您可以安全地[1] * 5
获取数字列表,或[True] * 5
获取真实列表,或['A'] * 5
获取字符列表'。区别在于您是否最终更改列表,或者您是否更改了列表引用的事物。顶级或二级。
e.g. making a list of numbers, assinging to it does this:
before:
nums = [1] * 3
list_start
entry 0 --> 1
entry 1 --> 1
entry 2 --> 1
list_end
nums[0] = 8
after:
list_start
entry 0 -xx 1
\-> 8
entry 1 --> 1
entry 2 --> 1
list_end
虽然按照您的方式制作字典列表并分配给它,但是这样做:
before:
blocks = [{}] * 3
list_start
entry 0 --> {}
entry 1 --/
entry 2 -/
list_end
first_block = blocks[0]
first_block['test'] = 8
after:
list_start
entry 0 --> {'test':8}
entry 1 --/
entry 2 -/
list_end
在第一个示例中,列表中的一个引用必须更改。您无法从列表中提取数字并更改数字,您只能在列表中添加不同的数字。
在第二个示例中,列表本身根本没有变化,您将分配给列表引用的字典。因此,虽然您感觉要更新列表中的每个元素,但实际上并非如此,因为列表中没有字典,并且引用了字典在其中。