Python 2.7版抛出ValueError异常:list.remove(X):X不在列表中(Py

2019-07-17 18:22发布

我每次运行这个程序,我得到这个错误:

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) 。 只是为了澄清,无论是aliensbolts是字典的名单。

我究竟做错了什么?

Answer 1:

你不应该从你遍历一个列表中删除项目。 创建一个副本,而不是:

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


Answer 2:

有一个在你的代码中的错误导致此。 您的代码,简化的,是这样的:

for b in bolts:
  for a in aliens:
    for a in aliens:
      bolts.remove(b)

这是造成你遍历aliens多次在每个条目b 。 如果B在在第一循环中去除aliens的话,当上循环,第二次,你会得到有错误。

有几件事情来解决。 首先,在内部循环换过来aliens使用其他的东西比a ,因此:

for b in bolts:
  for a in aliens:
    for c in aliens:
      if hit:
        bolts.remove(b)

其次,只删除bbolts一次。 所以:

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)

还有其他问题与此代码为好,但是我认为,这是导致你的主要问题。 马亭的帖子也可能会有帮助。



Answer 3:

给螺栓“健康”为好,初始化为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))


文章来源: Python 2.7 throws ValueError: list.remove(x): x not in list