这是代码:
def init_dic(init):
return {str(i):init for i in range(0,5)}
a = init_dic([])
print('Origin: ', a)
a['1'].append('test')
print('After append: ', a)
结果:
Origin: {'3': [], '4': [], '0': [], '1': [], '2': []}
After append: {'3': ['test'], '4': ['test'], '0': ['test'], '1': ['test'], '2': ['test']}
但我希望结果应该是:
Origin: {'3': [], '4': [], '0': [], '1': [], '2': []}
After append: {'3': [], '4': [], '0': [], '1': ['test'], '2': []}
为什么会这样?我不知道怎么回事......
所以如果我想要正确的结果,我该如何纠正我的代码?
答案 0 :(得分:3)
问题在这里:
def init_dic(init):
return {str(i):init for i in range(0,5)}
返回的字典将具有指向内存中相同对象的值:
>>> a['1'] is a['2']
True
通过复制init:
来避免这种情况def init_dic(init):
return {str(i):init[:] for i in range(0,5)}
推荐阅读:
http://docs.python-guide.org/en/latest/writing/gotchas/ https://docs.python.org/2.7/reference/datamodel.html#objects-values-and-types
答案 1 :(得分:1)
您的所有dict
值都是对同一list
个对象的引用。附加到它将影响所有这些。当init
param可变时,将始终出现此问题。对于不可变参数(int,float,tuple等),它将起作用。
您可以执行以下操作(如果您知道init
将是list
):
def init_dic(init):
return {str(i): init[:] for i in range(0,5)} # use a copy
更通用的方法是将工厂(产生实际值的0参数可调用)提供为init
并使用如下:
def init_dic(init):
return {str(i): init() for i in range(0,5)} # factory is called for each iteration
a = init_dic(lambda: [])
# a = init_dic(list)
正如小次郎所指出的那样,这就像一个defaultdict
,虽然是一个渴望和有限数量的钥匙。