将自变量作为参数传递给mixin父方法的正确方法

问题描述 投票:1回答:1

我必须为战士和他可以执行的各种攻击建模。这个想法是使用mixins包含攻击逻辑。我通过以下方式定义了我的课程:

class Warrior:
    def __init__(self, energy):
        self.energy = energy


class TemplarKnight(Warrior, HandToHandCombatMixin):
    pass


class CombatMixin:
    def __init__(self):
        self.attacks_cost = {}

    def attack(self, attacker, attack_cost):
        if attacker.energy < attack_cost:
            print('Not enough energy to attack')
        else:
            attacker.energy -= attack_cost
            print('Attack!')


class HandToHandCombatMixin(CombatMixin):
    def __init__(self):
        super().__init__()
        self.attacks_cost['sword_spin'] = 10

    def sword_spin(self, attacker):
        return self.attack(attacker, self.attacks_cost['sword_spin'])

但是问题出在我尝试测试此设置时。当我这样做

class TestTemplarKnight(unittest.TestCase):
    def setUp(self):
        self.templar = TemplarKnight(energy=100)

    def test_templar_knight_can_sword_spin(self):
        self.templar.sword_spin(self.warrior)
        self.assertEquals(self.templar.energy, 90)

我知道

    def sword_spin(self, attacker):
        return self.attack(
>           attacker, self.attacks_cost['sword_spin'])
E       AttributeError: 'TemplarKnight' object has no attribute 'attacks_cost'

[似乎Python认为参数self.attacks_cost(在self.attack()类的sword_spin()方法内调用HandToHandCombatMixin时,属于TemplarKnight类而不是HandToHandCombatMixin

我应该如何编写此代码以使Python在self.attacks_cost中查找HandToHandCombatMixin

python python-3.x oop inheritance mixins
1个回答
3
投票

要正确使用superall相关类需要使用它。现在,首先调用Warrior.__init__,但它不使用super,因此从不调用HandToHandCombatMixin.__init__

进行以下添加:

class Warrior:
    def __init__(self, energy, **kwargs):
        super().__init__(**kwargs)
        self.energy = energy


class TemplarKnight(Warrior, HandToHandCombatMixin):
    pass


class CombatMixin:
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.attacks_cost = {}

    def attack(self, attacker, attack_cost):
        if attacker.energy < attack_cost:
            print('Not enough energy to attack')
        else:
            attacker.energy -= attack_cost
            print('Attack!')


class HandToHandCombatMixin(CombatMixin):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.attacks_cost['sword_spin'] = 10

    def sword_spin(self, attacker):
        return self.attack(attacker, self.attacks_cost['sword_spin'])

现在实例化TemplarKnight时,您将保证以正确的顺序调用所有__init__方法。最终,一旦对super()的调用将导致object.__init__被调用,这时链最终结束。如果您正确地处理了关键字参数,那么**kwargs在发生时将为空。

© www.soinside.com 2019 - 2024. All rights reserved.