Python - Обновление атрибутов класса - PullRequest
0 голосов
/ 24 марта 2020

Мне нужна помощь с обновлением моих __init__ атрибутов, мне нужно их динамически обновлять. Поэтому ферма my __init__ выглядит следующим образом:

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()

Я хотел бы обновить эти значения по мере продвижения программы. Функция, которую я пытаюсь использовать, выглядит следующим образом:

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:])

есть ли способ, которым я могу изменить свои атрибуты при использовании dict как этот?

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

В данный момент значения dict являются значениями этих атрибутов, но я хотел бы изменить их без необходимости жесткого кодирования с большим количеством if's

Спасибо за помощь

Ответы [ 3 ]

1 голос
/ 24 марта 2020

Я не уверен, получил ли я именно то, что вам нужно, но, возможно, вы просто упускаете вызовы getattr и setattr.

Они позволяют вам изменить атрибут экземпляра, задав имя атрибута как строка. Как и в setattr(self, "armor", statistic_dict["Armor"]), или, как здесь будет полезно: setattr(self, item_name, statistic_dict["Armor"]) (имя атрибута теперь используется из переменной item_name и его не нужно жестко кодировать)

(Оба вызываемых являются частью из Python встроенных и вам не нужно импортировать их из любого места, просто используйте их - также, помимо получения и настройки, вы можете использовать hasattr и delattr)

Кроме того, у вас есть некоторые проблемы, связанные с тем, как вы создаете содержимое operator и value и используете его потом - если вы передаете -5 в строке, скажем, внутри переменной amount, просто выполнение my_value += int(amount) работает - нет необходимости вручную проверять «operator», так как «+» и «-» являются действительными префиксами при преобразовании целых чисел в строках в целые.

0 голосов
/ 24 марта 2020

Вот кое-что, что должно вас немного продвинуть.

Элемент - это собственный класс, который может иметь несколько модификаторов в словаре. Если ключ модификатора совпадает с существующим атрибутом героя, он добавляется к герою.

По мере продвижения go вы можете захотеть, чтобы значения модификатора были сами по себе классом. Ворпалец может иметь абсолютный шанс 70% крита, независимо от того, кто его использует. Или кольцо воровства может умножить ваш базовый chance_to_steal на 1,3 (то есть .30 * 1.3 = .39 сейчас).

Отдельный статистический указ может позволить вам отделить текущие значения от основные атрибуты героя, чтобы вы могли забрать предметы.

Не берите в голову то, что я сделал с вашими бедными Hero и Backpack классами, они не имеют значения для этой проблемы, поэтому я в основном закомментировал их.

# 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
0 голосов
/ 24 марта 2020

Похоже, вашей главной проблемой является отсутствие комфорта с логическими выражениями:

    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:])

Вместо:

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

Или с использованием троичного оператора (условное выражение):

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

Это обновляет статистику на + бонус или -bonus, в зависимости от оператора.


Обратите внимание, что это изменяет только значения в вашем dict; не изменяет атрибуты экземпляра ( не атрибуты класса). Если вы хотите изменить их, я рекомендую переместить соответствующие атрибуты в dict как часть вашей функции __init__, а затем оперировать этим self.capabilities dict как целью вашего add_item метода.

...