简体   繁体   English

Python 抛出 ValueError: list.remove(x): x not in list

[英]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.澄清一下, aliensbolts都是字典列表。

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM