[英]Python throws ValueError: list.remove(x): x not in list
Every time I run this program, I get this error:每次我运行这个程序,我都会得到这个错误:
ValueError: list.remove(x): x not in list
I am trying to lower the health of a single alien whenever it is hit by a bolt.每当被螺栓击中时,我都试图降低单个外星人的健康状况。 That single alien should also be destroyed if its health is
<= 0
.如果那个外星人的健康状况
<= 0
,它也应该被摧毁。 Similarly, the bolt would also be destroyed.同样,螺栓也将被破坏。 Here is my code:
这是我的代码:
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
The ValueError
happens on the line aliens.remove(a)
. ValueError
发生在aliens.remove(a)
行。 Just to clarify, both the aliens
and bolts
are lists of dictionaries.澄清一下,
aliens
和bolts
都是字典列表。
What am I doing wrong?我究竟做错了什么?
You should not remove items from a list you are looping over.你不应该从你正在循环的列表中删除项目。 Create a copy instead:
改为创建副本:
for a in aliens[:]:
and和
for b in bolts[:]:
Modifying a list while looping over it, affects the loop:在循环时修改列表会影响循环:
>>> lst = [1, 2, 3]
>>> for i in lst:
... print i
... lst.remove(i)
...
1
3
>>> lst
[2]
Removing items from a list you are looping over twice makes things a little more complicated still, resulting in a ValueError:从您循环两次的列表中删除项目会使事情变得更加复杂,从而导致 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
When creating a copy of the lists you are modifying at each level of your loops, you avoid the problem:在创建您在循环的每个级别修改的列表的副本时,您可以避免这个问题:
>>> 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]
When you have a collision, you only need to remove the b
bolt once , not in the loop where you hurt the aliens.当你发生碰撞时,你只需要移除
b
螺栓一次,而不是在你伤害外星人的循环中。 Clean out the aliens separately later:稍后单独清理外星人:
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
There is a bug in your code that is causing this.您的代码中存在导致此问题的错误。 Your code, simplified, looks like:
您的代码经过简化,如下所示:
for b in bolts:
for a in aliens:
for a in aliens:
bolts.remove(b)
That is causing you to loop over aliens
multiple times for every entry in b
.这导致您为
b
每个条目多次循环aliens
。 If the b is removed on the first loop over aliens
then, when it loops over it a second time, you will get there error.如果 b 在
aliens
的第一次循环中被删除,那么当它第二次循环时,你会得到那里的错误。
A few things to fix.一些事情要解决。 First, change in the inner loop over
aliens
to use something other than a
, so:首先,改变
aliens
的内部循环以使用a
以外a
东西,所以:
for b in bolts:
for a in aliens:
for c in aliens:
if hit:
bolts.remove(b)
Second, only remove b
from bolts
once.其次,只从
bolts
取下b
一次。 so:所以:
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)
There are other issues with this code as well, I think, but that is the cause your main problem.我认为此代码还有其他问题,但这是导致您的主要问题的原因。 Martijn's post may also help.
Martijn 的帖子也可能有所帮助。
you can not use list.remove you should use del list[x]你不能使用 list.remove 你应该使用 del list[x]
Because when you use remove you must name the deleted item by name not by index, so when the code is operated this error will appear (value error: x is not in list) But when we use del it is ok because we delete item by its index.因为当你使用remove时你必须按名称而不是索引来命名被删除的项目,所以当代码操作时会出现这个错误(值错误:x不在列表中)但是当我们使用del时就可以了,因为我们删除项目它的索引。 Whatever the item's name is, using del, the code will operate correctly I hope i cleared the problem and solved it
无论项目的名称是什么,使用del,代码都会正确运行我希望我清除了问题并解决了它
To know what i mean exactly please try this code Then try it by repacing del with remove and you will know what i mean.要确切地知道我的意思,请尝试此代码然后通过用删除重新调整 del 来尝试它,您就会知道我的意思。 The code is below:
代码如下:
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
Give the bolts a "health" as well, initialized to 1. Then you can do one nested loop to calculate all the damage, and two separate unnested "loops" to remove everything that's "dead".也给螺栓一个“健康”,初始化为 1。然后你可以做一个嵌套循环来计算所有的伤害,和两个单独的非嵌套“循环”来删除所有“死”的东西。 Except, don't do it quite like that, because you still don't want to modify the list that you're looping over.
除了,不要那样做,因为您仍然不想修改您正在循环的列表。 Making a copy is still too complicated.
制作副本还是太复杂了。 What you really want to do is directly build a new list of only the still "alive" things , and you can do that descriptively with list comprehensions (or as shown here, with
filter
).您真正想要做的是直接构建一个仅包含仍然“活着”的事物的新列表,您可以使用列表推导式(或如此处所示,使用
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))
I think if you replaced for loop with while loop - only in loop in which you remove from list - will solve it我认为如果你用 while 循环替换 for 循环 - 只有在你从列表中删除的循环中 - 将解决它
Like this像这样
lis = [1,2,3,4,5,6]
i=0
while i in range(len(lis)) :
lis. remove(lis[i])
I recommend this:我推荐这个:
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']):
a['health'] -= 1
bolts.remove(b)
if a['health'] == 0:
aliens.remove(a)
# Return bolts, aliens dictionaries
return bolts, aliens
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.