【问题标题】:AttributeError: NoneType object has no attribute 'health'AttributeError:NoneType 对象没有属性“健康”
【发布时间】:2012-05-28 19:00:41
【问题描述】:

我在我的策略游戏 Table Wars 的长时间比赛中遇到了这个错误。每当战场上有许多单位时,它似乎就会发生。这是回溯:

Traceback (most recent call last):
  File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 727, in <module>
    main()
  File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 131, in main
RedTeam.update()
  File "C:\Python27\lib\site-packages\pygame\sprite.py", line 399, in update
for s in self.sprites(): s.update(*args)
  File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 372, in update
self.attack()
  File "C:\Users\Oventoaster\Desktop\Games\Table Wars\Table Wars.py", line 393, in attack
    self.target.health -= self.attack_damage
AttributeError: 'NoneType' object has no attribute 'health'

该异常似乎出现在目标和攻击代码中,所以我将它们发布在这里:

def move_toward(self, target):
    if self.target is None:
        self.rect.move_ip(1, 0)

def update(self):
    self.find_target()
    self.move_toward(self.target)
    self.attack()
    if self.health <= 0:
        self.kill()

def find_target(self):
    if self.target is not None: return
    for enemy in BluTeam.sprites():
        if enemy.rect.centerx - self.rect.centerx <= self.range and enemy.rect.centery - self.rect.centery <= self.range:
            self.target = enemy
            return
        self.target = None

def attack(self):
    global REDGOLD
    global BLUECOMMAND
    if self.target is None: return
    if self.target.health <= 0:
        REDGOLD += self.target.reward
        BLUECOMMAND += self.target.cmdback
        self.target = None
    if not self.cooldown_ready(): return
    self.target.health -= self.attack_damage

def cooldown_ready(self):
    now = pygame.time.get_ticks()
    if now - self.attack_last >= self.attack_cooldown:
        self.attack_last = now
        return True
    return False

我该如何解决这个问题?

【问题讨论】:

    标签: python debugging pygame


    【解决方案1】:

    一个常见错误的解释或如何更好地理解一个简单的回溯来调试我的程序

      File "<path>\<filename>.py", line 393, in <function>
    

    Traceback 为您提供调用堆栈并指出错误在哪个函数中引发。这里没什么特别的

        self.target.health -= self.attack_damage
    

    友好的解释器给出导致错误的语句。这很重要,因为这意味着引发的错误与这行代码有关。

    AttributeError: 'NoneType' object has no attribute 'health'
    

    我们到了。错误是 AttributeError ;文档对此非常清楚:我正在尝试读取的值或我正在尝试分配给不是相关对象成员的变量。

    我的对象是什么?这是一个'NoneType' object;我们没有名字,但我们有它的类型。我们遇到问题的对象是NoneType,因此它是特殊对象None

    这个 Noneobject 有什么错误?它没有 'health' 属性表示 Traceback。因此,我们在错误引发的代码行中的某处访问属性 health,这在 None 对象上调用。

    现在我们几乎都准备好了:self.target.health 是我们使用health 的错误行中的唯一位置,因此这意味着self.targetNone。现在我查看源代码,我试图理解为什么会这样,即使我在函数的开头对它进行了检查。这导致我必须在该行之后以某种方式将其设置为None


    所有这些推理步骤都会得出简短的答案:

    这意味着self.targetNone。错误来自您的代码:

    if self.target.health <= 0:
        REDGOLD += self.target.reward
        BLUECOMMAND += self.target.cmdback
        self.target = None  # set to None
    if not self.cooldown_ready(): return
    self.target.health -= self.attack_damage  # self.target is None, .health failed
    

    【讨论】:

    • +1。我从来没有见过有人在这里花时间详细解释追溯。干得好,希望对 OP 有所帮助。
    • 啊,所以你是说我应该把伤害线放在我的杀戮块之前?
    • @Oventoaster 我想是这样,否则你将拥有一个僵尸和不死生物即使被杀死也仍然在移动的游戏。重要的是要了解如何使用调试信息(不应为 None 的 None 对象)来回到您的算法设计问题(在损坏之前检查死亡)
    猜你喜欢
    • 1970-01-01
    • 2018-06-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-30
    • 1970-01-01
    • 2019-08-09
    相关资源
    最近更新 更多