【问题标题】:For Loop Over Dictionaries in List (Python 2.7.6)For 循环遍历列表中的字典(Python 2.7.6)
【发布时间】:2015-10-30 18:24:48
【问题描述】:

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

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}]

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

对我来说更奇怪的是,如果我通过了:

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

然后运行 ​​for 循环,使其追加两个字典,循环在第一个上运行良好,然后复制最后两个的值。我认为这是原因和解决方案,尽管我对此太陌生,无法从问题中辨别出来。

非常感谢您帮助我了解为什么会发生这种情况。

谢谢

【问题讨论】:

  • 您正在用对同一字典的引用填充y。不要那样做。

标签: python list for-loop dictionary


【解决方案1】:

您感到困惑的原因是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}]

【讨论】:

  • 非常感谢您的解释,以及对列表理解的进一步演示。我的逻辑缺陷是认为它确实只是复制变量的值,而不是复制变量本身。
【解决方案2】:

正如其他人指出的那样,您将引用附加到同一个字典

使用复制模块中的 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

【讨论】:

  • 虽然copy.deepcopy() 对于一般情况,dict.copy() 方法在这里就足够了,因为所有值都是简单的不可变类型 - ints 和 strs。
  • 非常感谢您的回答以及将我介绍给复制模块的补充。如果我的赞成票对任何事情都有影响,那么您至少会有一个。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 2014-06-27
  • 2019-07-10
  • 2019-03-22
  • 2023-03-18
  • 1970-01-01
相关资源
最近更新 更多