for循环和索引切片的组合不会返回预期的结果

时间:2017-12-07 12:36:53

标签: python for-loop indexing slice

提前道歉,我不愿问这样一个新问题(这是我正在学习的第一种语言),但我的理解中显然存在差距,我无法找到解决问题的任何内容的链接我正在经历。

以下代码定义了3个词典和一个空列表。然后我运行一个for循环,用30“Slow Aliens”填充列表。

然后我在列表中的前10个条目上运行另一个循环,以便将该特定实例更新为“Fast Alien”字典。但是,我似乎正在替换列表中的每个字典。

任何帮助指向我进一步讨论/解决/教育我的文章都会受到赞赏。

slow_alien = {
    "Name": "Slow Alien",
    "Colour": "Green",
    "Points": 10,
    "X Position": 15,
    "Y Position": 20,
    "Current Speed": "Slow",
    "Height": 1.8,
}
medium_alien = {
    "Name": "Medium Alien",
    "Colour": "Yellow",
    "Points": 15,
    "X Position": 30,
    "Y Position": 20,
    "Current Speed": "Medium",
    "Height": 2.2,
}
fast_alien = {
    "Name": "Fast Alien",
    "Colour": "Red",
    "Points": 20,
    "X Position": 45,
    "Y Position": 20,
    "Current Speed": "Fast",
    "Height": 2.6,
}
aliens = []

for alien in range(30):
    aliens.append(slow_alien)

for alien in aliens[:10]:
    if alien == slow_alien:
        alien.update(fast_alien)

for alien in aliens:
    for key, value in alien.items():
        print(str(key) + ": " + str(value))
    print("")
print("The aliens list contains " + str(len(aliens)) + " dictionaries")

谢谢,

卡尔。

3 个答案:

答案 0 :(得分:1)

你说:

I then run a for loop to populate the list with 30 "Slow Aliens".

但那是错的,你实际上用一个慢速外星人填充了30次列表。

如果您确实想要其中30个,则在将它们添加到列表时必须复制。

for alien in range(30):
    aliens.append(slow_alien.copy())

答案 1 :(得分:1)

该列表包含30个对同一slow_alien字典的引用。

要解决此问题,请尝试以下方法:

aliens = []

for _ in range(30):
    aliens.append(slow_alien.copy())

for alien in aliens[:10]:
    alien.update(fast_alien)

遵循您当前的方法,但您也可以跳过更新并立即创建快速更新:

aliens = []

for _ in range(10):
    aliens.append(fast_alien.copy())
for _ in range(20):
    aliens.append(slow_alien.copy())

答案 2 :(得分:1)

正如已经指出的那样,创建字典的新副本是正确的答案。我想更明确地说明你的代码究竟出了什么问题。

for alien in range(30):
    aliens.append(slow_alien)

slow_alien指的是同一个dict,所以你得到30个(同一个)对象的引用。

for alien in aliens[:10]:
    if alien == slow_alien:
        alien.update(fast_alien)

update()电话会让一切变得混乱。循环中的第一个alien是对slow_alien dict的引用。所以你真正做的是slow_alien.update()并且你有效地改变了对象本身。它将成功进入剩余迭代的条件块,因为每个alienslow_alien引用相同的对象,即fast_alien。如果您在代码末尾打印slow_alien == fast_alien,则可以看到此内容。

如果每个项目都是不同的副本,则您更新该副本本身而不触及原始slow_alien。它也可以通过列表理解更紧凑地编写。

aliens = [slow_alien.copy() for _ in range(30)]