每次运行此程序时,都会收到此错误:
ValueError: list.remove(x): x not in list
我试图降低一个外星人的健康状况。如果它的健康状况是<= 0
,那么这个外国人也应该被摧毁。同样,螺栓也会被摧毁。这是我的代码:
def manage_collide(bolts, aliens):
# Check if a bolt collides with any alien(s)
for b in bolts:
for a in aliens:
if b['rect'].colliderect(a['rect']):
for a in aliens:
a['health'] -= 1
bolts.remove(b)
if a['health'] == 0:
aliens.remove(a)
# Return bolts, aliens dictionaries
return bolts, aliens
ValueError
发生在aliens.remove(a)
行。只是为了澄清,aliens
和bolts
都是字典列表。
我做错了什么?
答案 0 :(得分:20)
您不应从正在循环的列表中删除项目。改为创建副本:
for a in aliens[:]:
和
for b in bolts[:]:
在循环上修改列表会影响循环:
>>> lst = [1, 2, 3]
>>> for i in lst:
... print i
... lst.remove(i)
...
1
3
>>> lst
[2]
从循环两次的列表中删除项目会使事情变得更复杂,导致ValueError:
>>> lst = [1, 2, 3]
>>> for i in lst:
... for a in lst:
... print i, a, lst
... lst.remove(i)
...
1 1 [1, 2, 3]
1 3 [2, 3]
Traceback (most recent call last):
File "<stdin>", line 4, in <module>
ValueError: list.remove(x): x not in list
创建要在循环的每个级别修改的列表副本时,可以避免此问题:
>>> lst = [1, 2, 3]
>>> for i in lst[:]:
... for i in lst[:]:
... print i, lst
... lst.remove(i)
...
1 [1, 2, 3]
2 [2, 3]
3 [3]
当你发生碰撞时,你只需要移除b
螺栓一次,而不是在你伤害外星人的环路中。稍后分别清理外星人:
def manage_collide(bolts, aliens):
for b in bolts[:]:
for a in aliens:
if b['rect'].colliderect(a['rect']) and a['health'] > 0:
bolts.remove(b)
for a in aliens:
a['health'] -= 1
for a in aliens[:]:
if a['health'] <= 0:
aliens.remove(a)
return bolts, aliens
答案 1 :(得分:2)
您的代码中存在导致此问题的错误。您的代码简化,如下所示:
for b in bolts:
for a in aliens:
for a in aliens:
bolts.remove(b)
这导致您为aliens
中的每个条目多次循环b
。如果在aliens
上的第一个循环中删除了b,那么当它第二次循环时,你就会出错。
要解决的一些问题。首先,更改内部循环aliens
以使用a
以外的内容,所以:
for b in bolts:
for a in aliens:
for c in aliens:
if hit:
bolts.remove(b)
其次,仅从b
移除bolts
一次。这样:
for b in bolts:
for a in aliens:
should_remove = False
for c in aliens:
if hit:
should_remove = True
if should_remove:
bolts.remove(b)
我认为此代码还存在其他问题,但这是导致您的主要问题。 Martijn的帖子也可以提供帮助。
答案 2 :(得分:1)
您不能使用list.remove 您应该使用del list [x]
由于使用remove时,必须按名称而不是按索引来命名已删除的项目,因此在操作代码时会出现此错误(值错误:x不在列表中) 但是,当我们使用del时,这是可以的,因为我们通过其索引删除了项。 无论项目的名称是什么,使用del都可以正确运行代码 我希望我能解决问题并解决
要知道我的意思是什么 请尝试此代码 然后通过用remove替换del来尝试它,您将了解我的意思。 代码如下:
aliens = [[4,3,2,1],[4,3,2,1],[4,3,2,1]]
print(aliens)
bolts = [b for b in range(1,30)]
for b in bolts:
del aliens[0][0]
print(aliens)
if len(aliens[0]) == 0:
del aliens[0]
if len(aliens) == 0
print("you win")
break
答案 3 :(得分:0)
也给螺栓一个“健康”,初始化为1.然后你可以做一个嵌套循环来计算所有的伤害,然后两个单独的无效“循环”来移除所有“死”。除此之外,不要那样做,因为你仍然不想修改你正在循环的列表。制作副本仍然太复杂了。你真正想做的是直接建立一个只有仍然“活着”的东西的新列表,你可以用列表推导来描述性地(或者如此处所示,filter
)
# for example
class Alien:
# ... other stuff
def damage(self): self.hp -= 1
def alive(self): return self.hp > 0
# similarly for Bolt
def collide(an_alien, a_bolt):
# etc.
def handle_collisions(aliens, bolts):
for a in aliens:
for b in bolts:
if collide(a, b):
a.damage()
b.damage()
return list(filter(Alien.alive, aliens)), list(filter(Bolt.alive, bolts))
答案 4 :(得分:0)
我认为,如果您将while循环替换为while循环-仅在从列表中删除的循环中才能解决
喜欢
lis = [1,2,3,4,5,6]
i=0
while i in range(len(lis)) :
lis. remove(lis[i])