2016-06-05 7 views
0

Ich arbeite gerade an einem kleinen RPG in Pygame, um mich an die objektorientierte Programmierung zu gewöhnen.Erstellen eines Klassenattributs abhängig von einem anderen Attribut

Beim Blick in, wie eine Eigenschaft Auto-Update ich über die folgende kam:

class P: 

    def __init__(self,x): 
     self.x = x 

    @property 
    def x(self): 
     return self.__x 

    @x.setter 
    def x(self, x): 
     if x < 0: 
      self.__x = 0 
     elif x > 1000: 
      self.__x = 1000 
     else: 
      self.__x = x 

Ich habe versucht, es zu meinem Code der Anwendung, aber ich erhalte die folgenden Fehler:

File "weapons.py", line 13, in __init__ 
    self.name = '{} {}'.format(ammo, self.raw_name) 

TypeError: name() takes exactly 3 arguments (2 given) 

Ich verstehe Was ist der Fehler, aber ich bekomme nicht, wie ich es lösen kann, da ich sowohl den Raw-Name als auch die Munition-Attribute benötige, um den Namen meiner Arrow-Instanz automatisch zu aktualisieren.

Meine Klasse ist als solche:

class Projectile(Item): 
    def __init__(self, name, value, image, x, y, speed, dmg, dmg_modif, ammo): 
     super(Projectile, self).__init__(name, value, image, x, y) 
     self.dest = (self.rect[0],self.rect[1]) 
     self.speed = speed 
     self.dmg_modif = dmg_modif 
     self.dmg = dmg 
     self.orientation = 0 
     self.ammo = ammo 

    @property 
    def name(self): 
     return self.___name 


    @name.setter 
    def name(self, raw_name, ammo): 
     if '{} {}'.format(raw_name,ammo) != self.___name: 
      self.___name = '{} {}'.format(raw_name,ammo) 

Das Kind Klasse, die den Fehler zurückgibt, ist:

class Arrow(Projectile): 
    def __init__(self, ammo): #name, value, image, x, y, dmg 
     self.raw_name = 'Arrows' 
     self.name = '{} {}'.format(ammo, self.raw_name) 
     self.value = 5 
     self.image = variables.quiver_img 
     self.speed = 4 
     self.dmg = 2 
     self.dmg_modif = 1 
     super(Arrow, self).__init__(self.name, self.value, self.image, 200, 150, self.speed, self.dmg, self.dmg_modif, ammo) 

Und die übergeordneten Klassen sind, Artikel und MySprite:

class Item(MySprite): 

    def __init__(self, name, value, image, x, y): 
     # Call the parent class (Sprite) constructor 
     super(Item, self).__init__(image, x, y) 

     self.name = name 
     self.value = value 
     self.inv_pos = -1 

und

class MySprite(pygame.sprite.Sprite): 
    def __init__(self,image,x,y): 

     # Call the parent class (Sprite) constructor 
     super(MySprite, self).__init__() 
     self.image = image 
     self.rect = self.image.get_rect().move(x, y) #initial placement 
     self.top_cp = (self.rect[0]+self.rect[2]/2,self.rect[1]) 
     self.bot_cp = (self.top_cp[0],self.rect[1]+self.rect[3]) 
     self.left_cp = (self.rect[0],self.rect[1]+self.rect[3]/2) 
     self.right_cp = (self.left_cp[0]+self.rect[2],self.left_cp[1]) 
     self.center = self.rect.center 
     self.pos = self.rect.topleft 
     self.blit_order = 1 
     self.level = variables.current_level #Level(1)#level to which sprite belongs 

Jede Hilfe wäre willkommen!

Antwort

0

Also mein Problem, das ich schließlich gelungen, zu lösen:

class Projectile(object): 
    def __init__(self, raw_name, ammo): 
     self.raw_name = raw_name 
     self.name = self.raw_name 
     self.ammo = ammo 

    @property 
    def ammo(self): 
     return self._ammo 

    @ammo.setter 
    def ammo(self, ammo): 
     self.name = str(ammo) + self.raw_name 
     self._ammo = ammo 


class Arrow(Projectile): 

    def __init__(self): 
     self.raw_name = ' Arrows' 
     self.name = self.raw_name 
     super(Arrow, self).__init__(self.raw_name, ammo 
     = 10) 

arrow = Arrow() 
print arrow.ammo 
print arrow.name 
arrow.ammo = 15 
print arrow.ammo 
print arrow.name 

gibt:

>>>10 
>>>10 Arrows 
>>>15 
>>>15 Arrows 
0

Bitte geben Sie beim nächsten Mal eine minimal example an.

Ihr Code sieht ein wenig kompliziert aus. OK, das erste Problem ist, dass Sie nicht mehrere Argumente an einen Setter übergeben können. Sie können entweder ein Tupel übergeben oder einfach die traditionelle Setter-Methode def set_name(self, name, ammo): verwenden.

Ein weiteres Problem ist, dass Sie das Attribut ___name verwenden, bevor es festgelegt wurde, z. B. in der zweiten Zeile der Arrow s __init__ Methode.

Private Attribute sollten einen Unterstrich haben, nicht drei (das ist nur eine Konvention, um andere Programmierer zu warnen). Wenn Sie zwei oder mehr Unterstriche haben, wird der Name mangled.

Auch sieht es für mich aus wie Sie den Namen im Setter nur ändern, wenn der neue Name gleich dem alten Namen ist (irgendwie sinnlos;)). Was möchtest du dort eigentlich machen? Vielleicht brauchst du überhaupt keine Eigenschaften.

Hier ist eine feste (minimal) Version des Codes:

import pygame 


class MySprite(pygame.sprite.Sprite): 

    def __init__(self): 
     super(MySprite, self).__init__() 


class Item(MySprite): 

    def __init__(self, name): 
     super(Item, self).__init__() 
     self.name = name 


class Projectile(Item): 
    def __init__(self, name): 
     super(Projectile, self).__init__(name) 

    @property 
    def name(self): 
     return self._name 

    @name.setter 
    def name(self, name): 
     self._name = name + ' foo' 


class Arrow(Projectile): 

    def __init__(self): 
     super(Arrow, self).__init__(name='Arrows') 

arrow = Arrow() 
print(arrow.name) 
arrow.name = 'New name' 
print(arrow.name) 
+0

Danke für die antworte ich werde das heute Abend versuchen. Grundsätzlich hoffe ich, dass jedes Mal, wenn die "Munitionszählung" geändert wird, der Name geändert wird. Der Grund dafür ist, dass ich den Namen im Inventar des Spielers anzeige. Wenn also der Spieler 10 Pfeile hat, möchte ich, dass der Name "10 Pfeile" ist, wenn aus irgendeinem Grund ein Pfeil entfernt wird (d. H. Munition - = 1), dann wird der Name auf "9 Pfeile" usw. aktualisiert ...Ich habe es geschafft, aber es ist mühsam, da ich alle möglichen Stellen im Spiel finden muss, an denen die Pfeilmunition geändert werden kann, und dann eine Zeile hinzufüge, um die Instanz umzubenennen. – Sorade

+0

Sie sind hier: (irgendwie sinnlos;). Ich meinte anders, ich habe die Frage bearbeitet. Auch mit einem oder zwei Unterstrichen vor dem Namen hatte ich den Fehler _classname__spam nicht vorhanden, deshalb habe ich 3 Unterstriche eingefügt. – Sorade