2016-03-31 4 views
0

Итак, я создал класс и хочу, что атрибут hp всегда остается между 0 и maxhp В теории принятия hp свойство должно дать мне желаемый результат: каким-то образом он не работает.Свойство класса не ограничивает атрибут

Есть ли способ связать атрибуты для и обратно? Поэтому я сохранил позицию объекта класса единицы. В 2-х местах, после позиции атрибута, которая содержит массив [x, y], а в другое время его хранит в 2 атрибутах x и y и каждый содержит int. Изменение self.x или self.y должно изменить self.position и наоборот.

class units(object): 

    def __init__(self,typus, position, stats): 
     self.type = typus 

     #they should be linked both directions 
     self.position = position 
     self.x = self.position[0] 
     self.y = self.position[1] 

     self.attack = stats[0] 
     self.defense = stats[1] 
     self.maxhp = stats[2] 
     self.hp = self.maxhp 

    def __repr__(self): 
     text = "This a %s at position [%s,%s].\n Attack: %s \n Defense: %s \n Hp : %s/%s \n " \ 
       % (self.type,self.position[0],self.position[1], self.attack, self.defense, self.hp, self.maxhp) 
     return text 


    # hp set to always be in between 0 and maxhp 
    @property 
    def hp(self): 
     return self.__hp 

    @hp.setter 
    def hp(self, hp): 
     if hp < 0: 
      self.__hp = 0 
     if hp > self.maxhp: 
      self.__hp = self.maxhp 
     else: 
      self.__hp = hp 

    def takedmg(self,dmg): 
     self.hp -= max(dmg-self.defense, 0) 
     if self.hp <= 0: 
      self.alive = False 
     return self.hp 



p = units("peasant", [1,1], [2,0,30]) 
p.takedmg(100) 
print (p.hp)  # it should be 0! 
+0

И вместе с изменения, приведенные в моем ответе, рассмотрим использование ['str.format()'] (https://docs.python.org/3/library/string.html#format-string-syntax) для длинного '__repr__'. – aneroid

ответ

0

В вашем __init__ линия self.hp = self.maxhp должна быть self.__hp = self.maxhp. Таким образом, он установлен только в методах @property.

Вы бы обработали postion, x и y так же, как вы сделали для hp. Используйте _postion, _x и _y внутренне, чтобы соответствовать значениям в геттерах и сеттерах; и установить все значения _prop в сеттерах каждого из них. Использование position в качестве примера:

@property 
def position(self): 
    return self._position 

@position.setter 
def position(self, position): 
    self._position = position # do checking before this if needed 
    self._x = position[0] 
    self._y = position[1] 

Аналогично для x и y, хотя я думаю, что вы должны сделать это только через position:

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

@x.setter 
def x(self, x): 
    self._x = x 
    # self._y remains unchanged 
    self._position[0] = x 

BTW, hp сеттер может быть переписана следующим образом :

@hp.setter 
def hp(self, hp): 
    self.__hp = max(0, min(hp, self.maxhp)) 
+0

Спасибо, что помогли. Переписывание hp: мне очень нравится, что там действительно много атрибутов, которые нуждаются в подобном поведении. – Ryanless

+0

Да, я использую подобный подход для реализации такого поведения. Это тоже _pythonic_ способ сделать это - так почти все делают. Одна вещь, которую нужно добавить, вам обязательно нужна двойная подчёркиваемость имен для 'self .__ hp' vs' self._hp', которая считается частной? Это действительно необходимо, если вы не хотите, чтобы реализация подкласса мешала вам. – aneroid

+0

Ну, это был способ показать, когда я googeled, как использовать свойство. Так что нет никакой разницы. Один маленький вопрос «проверите перед этим, если нужно», что вы имеете в виду? – Ryanless

1

Другая проблема заключается в hp.setter. Второй if заявление следует заменить elif, потому что, когда hp меньше 0, self.__hp устанавливается в 0 в первом if, а затем, без elif, он устанавливается на отрицательное значение в else:

@hp.setter 
def hp(self, hp): 
    if hp < 0: 
     self.__hp = 0 
    elif hp > self.maxhp: 
     self.__hp = self.maxhp 
    else: 
     self.__hp = hp 
+0

Это не проблема, если 'maxhp' не может быть отрицательным. Поместите его как «elif'_is_ лучше/понятнее/оптимизировано, но это определенно не проблема. – aneroid

+0

Это настоящая проблема в примере кода. Когда hp <0 self .__ hp устанавливается в 0 в первом, если, то, без elif, устанавливается отрицательное значение в else. – apr

+0

Хороший момент, пропустил это. К счастью, «hp.setter», который я вложил в мой ответ, не имеет этой ошибки. Я отредактировал ваш ответ и добавил ваше объяснение (и отменил мой голос -ve)._ Тем не менее, это не вопрос вопроса OP, зависящий от значения. – aneroid

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