2012-05-28 7 views
0

내 전략 게임 인 Table Wars에서 오랜 시간 일치하는 동안이 오류가 발생합니다. 전장에 많은 유닛이있을 때마다 발생하는 것으로 보입니다. 여기에 역 추적입니다 :AttributeError : NoneType 객체에 'health'속성이 없습니다.

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 

가 어떻게이 문제를 해결합니까?

답변

8

일반적인 오류의 설명 또는 더 나은 내 프로그램을 디버깅하는 간단한 추적을 이해하는 방법을 :

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

역 추적 당신에게 오류 호출 스택 및 포인트를주는 어떤 함수에서 발생합니다. 여기에 특별하다.

self.target.health -= self.attack_damage 

친절한 해석기가 오류의 원인이되는 진술을 제공한다. 이는 발생 된 오류가이 코드 행과 관련되어 있음을 의미하므로 중요합니다.

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

여기 있습니다. 오류는 AttributeError입니다. 의사는 그것에 대해 꽤 명확합니다 : 값을 읽으려고하거나 관련 개체의 구성원이 아닌 변수에 할당하려고합니다.

내 개체는 무엇입니까? 그것은 'NoneType' object입니다; 우리에게는 이름이 없지만 그 유형이 있습니다. 문제가있는 객체는 NoneType이므로 특수 객체 None입니다.

None 개체의 오류는 무엇입니까? 그것은 흔적을 말하는 'health' 속성을 가지고 있지 않습니다. 그래서 우리는 오류 코드가있는 코드 라인 어딘가에서 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 
+0

+1. 나는 세부 사항에서 그 많은 것을 추적 할 수있는 시간을 가지면서 여기 누군가를 보지 못했다. 좋은 작품, 그것이 이익을 도왔 으면 좋겠어. – jadkik94

+0

아, 그러니 내 살인 블록 앞에 피해 라인을 놓아야한다고 말하는거야? – Oventoaster

+0

@Oventoaster 그렇지 않다고 생각하면 좀비와 언데드가 죽어도 게임이 계속 진행됩니다. 중요한 것은 알고리즘 디자인 문제 (손상되기 전에 사망 확인)로 돌아 가기 위해 디버깅 정보 (None이 아니어야 함)를 사용하는 방법을 이해하는 것입니다. – Boud

관련 문제