问题
I get this error during a lengthy match in my strategy game, Table Wars. It seems to occur whenever there are many units on the battlefield. Here is the traceback:
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'
The exception seems to appear in the targeting and attacking codes, so I will post them here:
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
How do I fix this?
回答1:
Explanation of a common error or how to better understand a simple traceback to debug my program:
File "<path>\<filename>.py", line 393, in <function>
Traceback gives you the callstack and points to the error raises in which function. Nothin special here
self.target.health -= self.attack_damage
Friendly interpreter gives the statement causing the error. This is important as it means the error raised is related to this line of code.
AttributeError: 'NoneType' object has no attribute 'health'
Here we are. The error is AttributeError ; the doc is pretty clear about it: I'm trying to read the value of or I'm trying to assign to a variable that is not a member of the related object.
What is my object ? It is a 'NoneType' object ; we don't have the name, but we have its type. The object we have an issue with is NoneType, thus it is the special object None.
What is the error with this Noneobject ? It doesn't have a 'health' attribute is saying the Traceback. So, we are accessing the attribute health somewhere in the line of code the error raises, and this is called on a None object.
Now we are almost all set: self.target.health is the only location in the error line we use health, thus it means self.target is None. Now I look at the source code I try to understand why it could be, even if I put a check at the beginning at the function against it. It leads to the fact I must set it to None somehow after that line.
All of this reasoning steps lead to the short answer:
It means self.target is None. The error comes from your code:
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
来源:https://stackoverflow.com/questions/10789296/attributeerror-nonetype-object-has-no-attribute-health