对于列表中的循环字典(Python 2.7.6)

时间:2015-08-07 10:26:08

标签: python list for-loop dictionary

对于我的生活,我无法弄清楚为什么会发生以下情况:

x = 2
y = []
z = { "player" : 0, "name": "none", "fired": 0, "hits": 0, "misses": 0, "streak": 0, "longest streak": 0 }

def number_player(x, y, z):
    for i in range(x):
        y.append(z)
        y[i]["player"] = (i + 1)

number_player(x, y, z)
print y

控制台返回:

[{'streak': 0, 'hits': 0, 'name': 'none', 'player': 2, 'misses': 0, 'longest streak': 0, 'fired': 0}, {'streak': 0, 'hits': 0, 'name': 'none', 'player': 2, 'misses': 0, 'longest streak': 0, 'fired': 0}]

简而言之,它会创建一个{...“播放器”:“2”......}的键/值对两次。如果我在每个循环结束时请求打印,则列表中第一个返回的字典包含{...“播放器”:“1”...}按预期的键/值对。

对我来说,如果我通过,那么陌生人仍然是:

x = 3
y = [{ "player" : 0, "name": "none", "fired": 0, "hits": 0, "misses": 0, "streak": 0, "longest streak": 0 }]

然后运行for循环,所以它附加了两个词典,循环在第一个上运行正常,然后复制最后两个的值。我认为这里的原因和决心是存在的,尽管我对这个问题太新了,无法从问题中辨别出来。

让我理解为什么会发生这种情况的帮助将不胜感激。

谢谢

2 个答案:

答案 0 :(得分:3)

您混淆的原因是第y.append(z)行。

这不附加字典z副本,而是附加z的同一个实例的另一个引用。

因此,在修改刚刚附加的字典的循环的最后一次迭代中,您还要修改在上一次迭代中附加的第一个字典。您的列表y实际上只是[z, z]

>>> print y
[{'streak': 0, 'hits': 0, 'name': 'none', 'player': 2, 'misses': 0, 'longest streak': 0, 'fired': 0}, {'streak': 0, 'hits': 0, 'name': 'none', 'player': 2, 'misses': 0, 'longest streak': 0, 'fired': 0}]
>>> y[0]
{'fired': 0,
 'hits': 0,
 'longest streak': 0,
 'misses': 0,
 'name': 'none',
 'player': 2,
 'streak': 0}
>>> y[0] is y[1]
True
>>> y[0]['player'] = 123
>>> y[1]['player']
123

创建结构的更加pythonic的方法是使用列表理解:

>>> def new_player(n, name="none"):
...     return {"player" : n, "name": name, "fired": 0, "hits": 0, "misses": 0, "streak": 0, "longest streak": 0}
... 
>>> y = [new_player(n) for n in range(2)]
>>> y
[{'fired': 0,
  'hits': 0,
  'longest streak': 0,
  'misses': 0,
  'name': 'none',
  'player': 0,
  'streak': 0},
 {'fired': 0,
  'hits': 0,
  'longest streak': 0,
  'misses': 0,
  'name': 'none',
  'player': 1,
  'streak': 0}]

答案 1 :(得分:1)

正如其他人所指出的那样,你将对同一个dictionairy的引用附加

从复制模块中使用deepcopy。

import copy

x = 2
y = []
z = { "player" : 0, "name": "none", "fired": 0, "hits": 0, "misses": 0, "streak": 0, "longest streak": 0 }

def number_player(x, y, z):
    for i in range(x):
        y.append(copy.deepcopy(z))
        y[i]["player"] = (i + 1)

number_player(x, y, z)
print y