2016-06-05 7 views
0

В настоящее время я работаю над небольшой RPG в Pygame, чтобы привыкнуть к объектно-ориентированному кодированию.Создание атрибута класса, зависящего от другого атрибута

При поиске в том, как автоматическое обновление свойство я наткнулся на следующее:

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 

Я попытался применить его к моему коду, но я получаю следующее сообщение об ошибке:

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

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

Я понимаю что ошибка, но я не понимаю, как ее решить, так как мне нужно как имя raw_name, так и атрибуты боеприпасов для автоматического обновления имени экземпляра Arrow.

Мой класс как таковой:

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) 

Дочерний класс, который возвращает ошибку является:

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) 

И родительские классы, Item и 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 

и

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 

Любая помощь была бы рада!

ответ

0

Так что я в конце концов удалось решить мою проблему:

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 

дает:

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

В следующем случае укажите minimal example.

Ваш код выглядит немного сложнее. ОК, первая проблема заключается в том, что вы не можете передавать несколько аргументов в сеттер. Вы можете либо передать кортеж, либо просто использовать традиционный метод setter def set_name(self, name, ammo):.

Другая проблема заключается в том, что вы использовали атрибут ___name до его установки, например, во второй строке метода Arrow s __init__.

Частные атрибуты должны иметь одно подчеркивание, а не три (это просто соглашение, предупреждающее других программистов). Если у вас есть два или более символа подчеркивания, чем имя получает mangled.

Кроме того, мне кажется, что вы меняете имя в сеттере только в том случае, если новое имя равно старому имени (kinda бессмысленно;)). Что вы на самом деле хотите сделать там? Возможно, вам не нужны свойства вообще.

Вот фиксированная (минимальная) версия кода:

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

Спасибо за ответ Я попробую сегодня. В основном, что я надеюсь достичь, так это то, что каждый раз, когда число «боеприпасов» изменяется, имя get изменяется. Причиной этого является то, что я показываю имя в инвентаре игрока. Поэтому, если у игрока 10 стрелок, я хочу, чтобы имя было «10 стрелок», если по какой-либо причине стрелка удалена (например, боеприпасы - = 1), то имя обновляется до «9 стрелок» и т. Д. ...Мне удалось это сделать, но это утомительно, так как мне нужно найти все возможные места в игре, где можно поменять патроны стрелками, а затем добавить строку для переименования экземпляра. – Sorade

+0

Вы находитесь прямо здесь: (kinda бессмысленно;). Я имел в виду разные, я редактировал вопрос. Кроме того, с одним или двумя символами подчеркивания до имени у меня была ошибка _classname__spam не существует, поэтому я положил 3 подчеркивания. – Sorade

Смежные вопросы