1

I was wondering if there is a smart way of updating instance variables by comparing the variable names to keys in a dictionary. At first, I had this idea, which was not very refined:

Example: 1

class Warrior:
  def __init__(self, name, **bonus_attributes):
    self.health = 1000
    self.damage = 100
    self.enrage = False

    for key, value in bonus_attributes.items():
      if key == "health":
        self.health += value
      elif key == "damage":
        self.damage += value
      elif key == "enrage":
        self.enrage = value
      else:
        continue


olaf = Warrior("Olaf")
print(olaf.__dict__)

gorm = Warrior("Gorm", health = -500, damage = 100, enrage = True)
print(gorm.__dict__)

It does solve my problem, but I would have to add comparisons for each keyword argument that I pass to the instance. My friend then told me it would be a good idea to also have the instance variables stored in a single dictionary, like so:

Example: 2

class Warrior:
  def __init__(self, name, **bonus_attributes):
    self.variables = {
        "health": 1000,
        "damage": 100,
        "enrage": False
    }

    for key, value in bonus_attributes.items():
        if key in self.variables:
            if isinstance(value, bool):
                self.variables[key] = value
            else:
                self.variables[key] += value


olaf = Warrior("Olaf")
print(olaf.__dict__)

gorm = Warrior("Gorm", health = -500, damage = 100, enrage = True)
print(gorm.__dict__)

This made comparisons easy and I think that this may very well be the most proper way of going about solving my problem. However, I am still curious to know if there could be a way of sticking to the first example, where the instance variables are declared on their own. I just need to make the second example of the for-loop work for those individual declarations.

Should I just keep the second implementation, suggested by my friend, or is there a way to modify my first example to be as easily comparable as the two dictionaries?

nyedidikeke
  • 6,899
  • 7
  • 44
  • 59
  • You could also look into `getattr` and `setattr`. I'm always hesitant to use them though. Maybe take a look at this: https://stackoverflow.com/questions/13982297/can-the-usage-of-setattr-and-getattr-be-considered-as-bad-practice – Caleb H. Feb 01 '20 at 16:29

1 Answers1

0

In the case that you know every single thing you want to be editable (as above), just define them as optional parameters in the constructor:

class Warrior:
  def __init__(self, name, health=None, damage=None, enrage=None):
    self.health = 1000 + (health or 0)
    self.damage = 100 + (damage or 0)
    self.enrage = enrage or False

olaf = Warrior("Olaf")
print(olaf.__dict__)

gorm = Warrior("Gorm", health = -500, damage = 100, enrage = True)
print(gorm.__dict__)

If for some reason you'd prefer not to do this, I would recommend the dictionary method from example 2.

Caleb H.
  • 1,657
  • 1
  • 10
  • 31