1

I would like to instantiate a class, say, Fighter with and without the attribute weapon_size. But when the attribute weapon_size is set (either at instantiation or later) I want to run some method which adds another attribute damage (and perhaps does some other calculations). I'm trying to do this by overloading the setattr function as below.

My question: is this the correct [and sensible] way to do this?

class Fighter(object):
    def __init__(self, prenom, weapon_size = None):
        self._prenom = prenom
        self._weapon_size = weapon_size
        if not weapon_size is None:
            self.AddWeapon(weapon_size)

    def __setattr__(self, name, value):
            if name == "weapon_size":
                print "Adding weapon"
                self.AddWeapon(value)
                self.__dict__['_' + name] = value
            else:
                self.__dict__[name] = value

    def AddWeapon(self, x):
        self._damage = x/2.

    @property
    def weapon_size(self):
        "Weapon size"
        return self._weapon_size
    @property
    def prenom(self):
        "First name"
        return self._prenom

U = Fighter('Greg')
U.weapon_size = 9
print U.weapon_size, U._damage
>> 9 4.5
W = Fighter('Jeff', weapon_size = 11)
print W.weapon_size, W._damage
>> 11 5.5
p-robot
  • 4,652
  • 2
  • 29
  • 38

1 Answers1

3

You can define a custom setter for the specific property.

@weapon_size.setter
def weapon_size(self, value):
    # custom code here
    self._weapon_size = value

EDIT: But really, at the end of the day, I think it's much cleaner for you to simply do:

class Fighter(object):
    def __init__(self, prenom, weapon_size=None):
        ...
        self.weapon_size = weapon_size
        ...

    @property
    def damage(self):
        if self.weapon_size:
            return self.weapon_size / 2
        return None
dursk
  • 4,435
  • 2
  • 19
  • 30
  • Perfect, thanks. Can I ask, what would be the downside to using __setattr__? That I handle cases that I shouldn't handle? – p-robot Jan 08 '15 at 20:58
  • Because properties were basically created for the exact problem you are trying to solve. Overriding any `__x__` method should always be avoided if possible. With `__setattr__` your modifying a method that gets called for all attributes, when all you care about is `weapon_size`. This way is more precise. – dursk Jan 08 '15 at 21:02