【问题标题】:"ValueError: list.remove(x): x not in list" is thrown when using a for x in list\"ValueError: list.remove(x): x not in list\" 在列表中使用 for x 时抛出
【发布时间】:2023-02-23 01:39:20
【问题描述】:

当子弹与墙壁碰撞时,我正试图从列表中删除它们。该程序正确地移除了一些子弹,但最终在子弹击中墙壁时抛出“ValueError: list.remove(x): x not in list”错误。

该错误发生在 Bullet 类的 delete() 方法中,并且仅在敌人发射子弹时发生。从玩家发射的子弹不会产生任何错误。

class Bullet(Turtle):
    def __init__(self, player, list):
        super().__init__()
        self.speed(0)
        self.ht()
        self.pu()
        self.color("white")
        self.goto(player.xcor(), player.ycor())
        self.setheading(player.heading())
        self.forward(40)
        self.list = list
        self.st()
    
    # move the bullet
    def move(self):
        self.forward(15)
        if self.ycor()>300 or self.ycor()< -300:
            self.delete()
            
    # delete the bullet
    def delete(self):
        self.ht()
        self.list.remove(self)




def update(counter):
    if len(enemies)>0 and player.alive: 
        # move each of the enemies
        for alien in enemies:
            alien.move()
            if alien.ycor() < - 200 or alien.distance(player)<30:
                player.delete()

        # randomly select an enemy to fire a bullet.
        if counter % 10 == 0:
            index = random.randint(0,len(enemies)-1)
            bullets.append(Bullet(enemies[index],bullets))

        # move each bullet fired by the enemies
        for bullet in bullets[:]:
            bullet.move()
            # check for collision with player
            if bullet.distance(player)<20:
                player.delete()
            # check for collision with a wall
            for wall in walls[:]:
                if bullet.distance(wall)<15:
                    wall.strike()
                    bullet.delete()
                        
                
        # move bullets fired by the player
        for bullet in player.rounds:
            bullet.move()
            # check for collision with an enemy
            for alien in enemies:
                if bullet.distance(alien)<20:
                    bullet.delete()
                    alien.delete(enemies)
    
        counter += 1
        screen.ontimer(lambda:update(counter),30)

我遇到了这个问题,因为该程序使用 for 循环使用 bullet in bullets 的语法迭代项目符号列表。尽管项目符号可能存在​​于列表中,但当程序尝试从同一个列表中删除它时,它无法删除。

我试图通过复制列表来解决问题,但这并没有帮助我修复错误。

【问题讨论】:

  • 当您想在迭代列表的同时从列表中删除项目时,常见的解决方案是迭代列表的副本,您需要从原始列表中删除项目,而不是从副本中删除。另外,为什么 Bullet 类包含一个列表?
  • 除了@jarmod 所说的list isba 是任何东西的糟糕名称,它会很快产生很难找到错误,恕我直言。没有完整的上下文,但项目符号类不应将项目符号列表作为属性。
  • 请问您可以使用minimal, reproducible amount,而不是粘贴所有代码吗?这将使调试变得容易得多。
  • 谢谢大家的建议:
  • 使用“列表”作为名称可能会造成混淆。在此上下文中,“列表”是指项目符号的集合。该程序将维护两个子弹列表:一个用于敌人发射的子弹,另一个用于玩家发射的子弹。项目符号对象存储它所属的列表似乎是循环的,但我想不出更好的方法让项目符号识别它应该从哪个列表中删除自己。

标签: python list loops


【解决方案1】:

发生这种情况的原因可能是您试图多次删除同一颗子弹,因为它满足多个墙壁碰撞条件。如果为每个碰撞墙调用wall.strike() 并不重要,那么我们可以添加一个break 来退出 for 循环。否则,我们可以进行条件删除。

        for wall in walls[:]:
            if bullet.distance(wall)<15:
                wall.strike()
                if bullet not in bullet.list:
                    bullet.delete()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-03
    • 2022-06-28
    • 2020-07-11
    • 2022-06-11
    • 2022-12-17
    • 2018-07-05
    相关资源
    最近更新 更多