Python 2.7抛出ValueError:list.remove(x):x不在列表中

时间:2013-01-02 17:51:19

标签: python list dictionary pygame

每次运行此程序时,都会收到此错误:

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都是字典列表。

我做错了什么?

5 个答案:

答案 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])