奇怪的是我使用的是迭代O.o
中构建的Python我有一个名为Card的课程。除其他外,卡还有一个名称和一个符号列表(字符串)。
这是我的一段代码(所有打印件都是出于调试目的)
# This prints all the names of the cards in the deck before the iteration.
print(str([card.name for card in self.thegame.game_deck.deck[0]]))
for card in self.thegame.game_deck.deck[0]:
if 'CASTLE' not in card.symbols:
self.thegame.game_deck.deck[0].remove(card)
print(card.name + ' was removed')
else: print(card.name + ' was not removed')
# This prints all the names of the cards in the deck after the iteration.
print(str([card.name for card in self.thegame.game_deck.deck[0]]))
奇怪的是,这是stdout上的输出:
['Writing', 'Tools', 'The Wheel', 'Sailing', 'Pottery', 'Oars', 'Mysticism', 'Me
talworking', 'Masonry', 'Domestication', 'Code of Laws', 'Clothing', 'City State
s', 'Archery', 'Agriculture']
Writing was removed
The Wheel was not removed
Sailing was removed
Oars was not removed
Mysticism was not removed
Metalworking was not removed
Masonry was not removed
Domestication was not removed
Code of Laws was removed
City States was not removed
Archery was not removed
Agriculture was removed
['Tools', 'The Wheel', 'Pottery', 'Oars', 'Mysticism', 'Metalworking', 'Masonry'
, 'Domestication', 'Clothing', 'City States', 'Archery']
您可以清楚地看到,第一个列表中有名称(具体为:'工具','陶器','服装')
在输出的第二部分没有打印出来,实际上它们都留在列表中(所有三个,顺便说一句,在它们的符号中有'CASTLE',应该删除)。
有人能看到我错过了什么吗?
答案 0 :(得分:7)
迭代时,不应从列表中删除项目。
迭代列表的副本:
for card in self.thegame.game_deck.deck[0][:]:
^^^ copies the list
或者创建一个包含您要保留的项目的新列表,然后重新分配:
game_deck = self.thegame.game_deck
game_deck.deck[0] = [card for card in game_deck.deck[0] if 'CASTLE' in card.symbols]
答案 1 :(得分:0)
您正在修改您正在迭代的列表。这是一个坏主意。相反,请将您想要保留的列表附加到单独的列表中,然后将其重新分配给卡片。
答案 2 :(得分:0)
您正在从您正在迭代的列表中删除项目。使用具有CASTLE图标的卡创建新列表,而不是删除具有图标的卡。
答案 3 :(得分:0)
详细说明执行此操作时会发生什么:
In [99]: l = range(5)
In [100]: for i in l:
l.remove(i)
print list(enumerate(l))
.....:
.....:
[(0, 1), (1, 2), (2, 3), (3, 4)]
[(0, 1), (1, 3), (2, 4)]
[(0, 1), (1, 3)]
当您更改列表时,您正在更改索引引用哪个项目,您可以在上面的列表中看到值4
。
答案 4 :(得分:0)
迭代删除的另一个常见替代方法是标记待删除的项目(改变列表中的值但不更改列表长度),然后进行第二次高速传递以过滤掉无保证的卡:
# This prints all the names of the cards in the deck before the iteration.
print(str([card.name for card in self.thegame.game_deck.deck[0]]))
for i, card in enumerate(self.thegame.game_deck.deck[0]):
if 'CASTLE' not in card.symbols:
self.thegame.game_deck.deck[0][i] = None
print(card.name + ' was marked to be removed')
else: print(card.name + ' was not removed')
# This does the actual removal
self.thegame.game_deck.deck[0][:] = filter(None, self.thegame.game_deck.deck[0])
# This prints all the names of the cards in the deck after the iteration.
print(str([card.name for card in self.thegame.game_deck.deck[0]]))