2016-03-31 8 views
0

私はクラスを作って、その属性hpは常に0とmaxhpの間にとどまっています 理論では、hpのプロパティは私に希望の結果を与える必要があります。クラスのプロパティは属性を制限しません

属性をリンクする方法はありますか?だから私はユニットクラスオブジェクトの位置を格納しています。 2つの場所では、[x、y]配列を含む属性位置ともう1つの属性属性x、yに格納され、それぞれにintが格納されます。 self.xまたはself.yを変更すると、self.positionが変更され、逆も同様です。あなたの__init__

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

と一緒に:hpが0未満である場合に、self.__hpは最初ifに0に設定され、その後、elifせずに、それはelseに負の値に設定されているため、2番目のif文はelifに置き換えてください私の答えで与えられた変更は、長い '__repr__'に対して[' str.format() '](https://docs.python.org/3/library/string.html#format-string-syntax)の使用を検討してください。 – aneroid

答えて

0

、ラインself.hp = self.maxhpself.__hp = self.maxhpでなければなりません。そうすれば、それは@propertyの方法でのみ設定/取得されます。

hpの場合と同じ方法で、postion,xyを処理します。 getterおよびsetterの値に対応するには、_postion,_xおよび_yを内部的に使用します。それぞれのセッターに_propの値をすべて設定します。例としてpositionを使用して:私は思うものの、xyのための同様

@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] 

あなたは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 

ところで、hpセッターを再書き込むことができます:

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

ありがとうございました。 hpの再印刷:私は実際には同じような振る舞いを必要とする実際にたくさんの属性を持っています。 – Ryanless

+0

はい、同様のアプローチを使用してこのような動作を実装しています。それはまた、それを行う_pythonic_方法です - だからほとんど誰もしません。一つのことを追加するには、あなたは必然的に 'self .__ hp'と' self._hp'の二重アンダースコア名のmanglingが必要ですか?サブクラスの実装があなたのものに干渉しないようにしたい場合にのみ必要です。 – aneroid

+0

それは私がgoogeledプロパティを使用する方法を示した方法でした。だから違いはありません。 1つの小さな質問 "これの前に必要な場合にチェックする"とはどういう意味ですか? – Ryanless

1

もう1つの問題はhp.setterです。

@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_ better/clearer/optimizedしかし、それは間違いなく問題ではありません。 – aneroid

+0

これは、サンプルコードでは本当の問題です。 hpが0より小さい場合、最初にelifなしの場合はself .__ hpが0に設定され、それ以外の場合は負の値に設定されます。 – apr

+0

良い点、それを逃した。幸いにも、私が答えてくれた 'hp.setter'には、そのバグはありません。私はあなたの答えを編集し、あなたの説明を追加しました(そして私の投票結果を取り消しました)。_それはOPの質問ではなく、依存する値を設定することであった。 – aneroid

関連する問題