2012-07-04 8 views
5

Sono un po 'nuovo per Python, ma ho familiarità con OOP. Sto cercando di scrivere un gioco usando PyGame. Fondamentalmente, il mio obiettivo è quello di rendere gli alberi ogni pochi secondi e spostare i rects degli alberi attraverso lo schermo.AttributeError: L'istanza di classe non ha il metodo __call__

Così qui è il mio codice:

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() 

Ma quando eseguo questo i primi alberi sono generati con successo ma poi la finestra PyGame chiuse e ottengo questo errore:

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

risposta

19

Suppongo che sia perché si ha un nome variabile tree (utilizzato in tree.render()) che è in conflitto con il nome della classe. Chiamarlo Tree sarebbe meglio (e più pythonic ^^).

+0

Stupido da parte mia non averlo notato, grazie! :) –

+1

Prego! – Emmanuel

4

È potrebbe voler chiamare la variabile tree nel ciclo for qualcosa di diverso da tree. Sta oscurando il nome della classe.

+0

Haha, così stupido da parte mia. Grazie! –

1

vostro contesto sono inquinati

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() 

il compilatore può pensa che non sono init della classe, ma chiede la sua chiamata funzione.

+1

In Python è possibile creare tipi chiamabili (tipi che implementano l'operatore 'call' tramite un metodo '__call__') e l'istanziazione viene effettivamente eseguita chiamando la classe, che implementa l'operatore di chiamata. IOW, tutto ciò che il compilatore vede è un'operazione di "chiamata", qualunque sia la sua esecuzione (e anche il fatto che l'oggetto chiamato sia o non implementi l'operatore di chiamata) venga determinato in fase di runtime. –