0

I need help with updating my __init__ attributes, I need to dynamically update them. So farm my __init__ looks like this:

class Thief(Hero):
    def __init__(self, chance_to_steal=0.3, chance_to_crit=0.3):
        super().__init__(hero_name="Thief", stamina=100)
        self.chance_to_steal = chance_to_steal
        self.chance_to_crit = chance_to_crit
        self.armor = 0
        self.backpack = Backpack()

I would like to update this values as the program goes forward The function i am trying to use looks like this:

def add_item(self, item_name, item_type, modifier_amount):
    self.backpack.add_new_item(item_name, item_type, modifier_amount)
    if item_name in ["Armor", "Weapon"]:
        value, statistic = modifier_amount.split(" ")
        statistic_dict = {"Armor": self.armor, "Weapon": self.attack_dmg}
        plus_minus = {"+": True, "-": False}
        operator = value[0]
        if plus_minus[operator]:
            statistic_dict[item_name] += int(value[1:])
        if not plus_minus[operator]:
            statistic_dict[item_name] -= int(value[1:])

is there any way that i can modify self attributes while using dict like that?

        statistic_dict = {"Armor": self.armor, "Weapon": self.attack_dmg}

At the moment dict values are the values of that attributes but i would like to modify them without having to hard code it with lots of if's

Thanks for help

2
  • 1
    Read up on update([other]) Commented Mar 24, 2020 at 19:11
  • "+3" and "-3" are both valid int literals; you can simply write statistic_dict[item_name] += int(value). Commented Mar 24, 2020 at 19:20

3 Answers 3

1

I am not sure if I got exactly what you want, but maybe you are just missing the getattr and setattr callables.

They allow you to change an instance's attribute given the attribute name as a string. As in setattr(self, "armor", statistic_dict["Armor"]), or, as will be useful here: setattr(self, item_name, statistic_dict["Armor"]) (the attribute name is now used from the variable item_name and don't need to be hardcoded)

(Both callables are part of Python builtins and you don't need to import them from anywhere, just use them - also, besides getting and setting, you can use hasattr and delattr)

Besides that you have some issues with the way you stract your operator and value contents and use then - if one passes -5 in a string, say inside a amount variable, just doing my_value += int(amount) works - no need to manually check the "operator" as both "+" and "-" are valid prefixes when converting integer numbers in strings to ints.

Sign up to request clarification or add additional context in comments.

1 Comment

That is brilliant, thank you for reminding me about setattr. It worked perfectly
0

Your main problem seems to be lack of comfort with Boolean expressions:

    plus_minus = {"+": True, "-": False}
    operator = value[0]
    if plus_minus[operator]:
        statistic_dict[item_name] += int(value[1:])
    if not plus_minus[operator]:
        statistic_dict[item_name] -= int(value[1:])

Instead:

    if value[0] == '+':
        statistic_dict[item_name] += int(value[1])
    else:
        statistic_dict[item_name] -= int(value[1])

Or, using a ternary operator (conditional expression):

    bonus = int(value[1])
    statistic_dict[item_name] += bonus if value[0] == '+' else -bonus

This updates the stat by either +bonus or -bonus, depending on the operator.


Note that this modifies only the values in your dict; it does not modify the instance attributes (not class attributes). If you want to modify those, instead, I recommend that you move the applicable attributes to a dict as part of your __init__ function, and then operate on that self.capabilities dict as the target of your add_item method.

Comments

0

Here's something that should get you a bit further.

Item is its own class and can have several modifiers, in a dictionary. If a modifier's key matches an existing attribute on the Hero, then it gets added to the Hero's.

As you go further, you may want to have you Modifier values be a class in its own right. A Vorpal may have an absolute 70% chance to crit, regardless of who is using it. Or a ring of thieving may multiply your base chance_to_steal by 1.3 (i.e .30 * 1.3 = .39 now).

A separate statistics dict could allow you to separate out the current values from the hero's underlying attributes so that you could take away items.

Never mind what I did to your poor Hero and Backpack classes, they don't matter for this problem, so I basically commented them out.

# class Thief(Hero):
class Thief:

    def __repr__(self):

        return f"{self.__class__.__name__}.chance_to_steal={self.chance_to_steal}, chance_to_crit={self.chance_to_crit}"


    def __init__(self, chance_to_steal=0.3, chance_to_crit=0.3):
        # super().__init__(hero_name="Thief", stamina=100)
        self.chance_to_steal = chance_to_steal
        self.chance_to_crit = chance_to_crit
        self.armor = 0
        self.backpack = {}

    def add_item(self, item):
        self.backpack[item.name] = item

        for attrname,mod in item.modifiers.items():
            #do we have something to modify, on this Hero?
            val = getattr(self,attrname, None)
            if val is None:
                continue
            else:
                #sum the previous value and the modifier
                setattr(self, attrname, val + mod)

class Item:
    def __init__(self, name, modifiers=None):
        self.name = name
        if modifiers:
            self.modifiers = modifiers.copy()

thief = Thief(chance_to_crit=0.4)

print(thief)

item = Item("vorpal", dict(chance_to_crit=0.2))
thief.add_item(item)

print(thief)

item = Item("cursed ring", dict(chance_to_crit=-0.1, chance_to_steal=-0.2, cast_spell=-0.2))
thief.add_item(item)

print(thief)

output

Thief.chance_to_steal=0.3, chance_to_crit=0.4
Thief.chance_to_steal=0.3, chance_to_crit=0.6000000000000001
Thief.chance_to_steal=0.09999999999999998, chance_to_crit=0.5000000000000001

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.