2012-07-04 10 views
5

Ich bin ein wenig neu bei Python, aber vertraut mit OOP. Ich versuche ein Spiel mit PyGame zu schreiben. Grundsätzlich ist es mein Ziel, Bäume alle paar Sekunden zu rendern und die Baumrecte über den Bildschirm zu bewegen.AttributeError: Klasseninstanz hat keine __call__ Methode

So, hier ist mein Code:

from collections import deque 
import pygame,random,sys 

pygame.init() 
size = 800,600 
screen = pygame.display.set_mode(size) 

class tree: 
    def __init__(self): 
      self.img = pygame.image.load("tree.png") 
      self.rect = self.img.get_rect() 
    def render(self): 
      screen.blit(self.img,self.rect) 
    def move(self,x,y): 
      self.rect = self.rect.move(x,y) 

#creating a queue of trees 
trees = deque() 

#appending the first tree on to the queue 
trees.append(tree()) 


while 1: 


    for event in pygame.event.get(): 
      if event.type == pygame.QUIT: sys.exit() 

    #appending tree() to trees queue every 300 ms 
    if pygame.time.get_ticks() % 300 == 0: 
      trees.append(tree()) 

    #rendering and moving all the tree rects of trees in the queue 
    for tree in trees: 
      tree.render() 
      tree.move(20,2) 
    pygame.display.flip() 

Aber wenn ich dies die ersten paar Bäume ausführen erfolgreich erzeugt aber dann das PyGame Fenster geschlossen, und ich bekomme diese Fehlermeldung:

Traceback (most recent call last): 
File "error.py", line 25, in <module> 
trees.append(tree()) 
AttributeError: tree instance has no __call__ method 

Antwort

19

Ich denke, es liegt daran, dass Sie einen Variablennamen haben tree (in tree.render() verwendet), die mit Ihrem Klassennamen kollidiert. Nennen Sie es Tree wäre besser (und mehr Pythonic ^^).

+0

Dumm von mir, das nicht bemerkt zu haben, danke! :) –

+1

Gern geschehen! – Emmanuel

4

Sie Vielleicht möchten Sie die tree Variable in der for Schleife etwas anderes als tree aufrufen. Es überschattet den Klassennamen.

+0

Haha, so dumm von mir. Vielen Dank! –

1

Ihr Kontext ist verschmutzt

while 1: 
    for event in pygame.event.get(): 
     if event.type == pygame.QUIT: sys.exit() 

    #appending tree() to trees queue every 300 ms 
    if pygame.time.get_ticks() % 300 == 0: 
     trees.append(tree()) <----------------------- second time, this tree is not your class, but the last instance of tree 

    #rendering and moving all the tree rects of trees in the queue 
    for tree in trees: <-------------------- here, the last tree will get name with tree 
     tree.render() 
     tree.move(20,2) 
    pygame.display.flip() 

die Compiler kann man denkt, ist nicht die Klasse init, sondern ruft seinen Aufruf Funktion.

+1

In Python können Sie aufrufbare Typen erstellen (Typen, die den Aufrufoperator über eine '__call__'-Methode implementieren), und die Instanziierung wird tatsächlich durch Aufrufen der Klasse ausgeführt, die den Aufrufoperator implementiert. IOW, alles, was der Compiler sieht, ist eine "Aufruf" -Operation, an der ausgeführt wird (und sogar die Tatsache, dass das aufgerufene Objekt den Aufrufoperator implementiert oder nicht implementiert), die zur Laufzeit bestimmt wird. –

Verwandte Themen