Python中攻击类方法如何访问调用者(英雄/怪物)的属性?
问题核心原因
你当前的代码里,attacks.hit是绑定到Attacks实例的方法,当把它赋值给my_hero.attack后,调用my_hero.attack(my_monster)时,方法里的self仍然指向Attacks实例,而不是Hero实例,自然找不到strength属性。
下面是几种可行的解决方法:
方法1:让角色类继承攻击类(最直观的面向对象方案)
让Hero和Monster直接继承Attacks,这样攻击方法里的self就指向角色实例,能直接访问strength:
class Attacks: def bite(self, who): print('I bite') who.health -= self.strength def hit(self, who): print('I hit') who.health -= self.strength class Hero(Attacks): def __init__(self, health, strength): self.health = health self.strength = strength # 给角色指定默认攻击方式 self.attack = self.hit class Monster(Attacks): def __init__(self, health, strength): self.health = health self.strength = strength self.attack = self.bite # 测试代码 my_hero = Hero(100, 10) my_monster = Monster(100, 10) print(my_monster.health) # 输出100 my_hero.attack(my_monster) print(my_monster.health) # 输出90
这种方案符合"角色具备攻击能力"的逻辑,代码简洁,不需要额外的绑定操作。
方法2:将攻击方法改为静态方法,传入攻击者参数
把Attacks里的方法改成静态方法,不需要依赖Attacks实例的self,而是直接接收攻击者和目标两个参数,再在角色初始化时用lambda把自身绑定进去:
class Attacks: @staticmethod def bite(attacker, who): print('I bite') who.health -= attacker.strength @staticmethod def hit(attacker, who): print('I hit') who.health -= attacker.strength class Hero: def __init__(self, health, strength, attack): self.health = health self.strength = strength # 包装攻击方法,让调用时只需要传目标 self.attack = lambda who: attack(self, who) class Monster: def __init__(self, health, strength, attack): self.health = health self.strength = strength self.attack = lambda who: attack(self, who) # 测试代码 attacks = Attacks() my_hero = Hero(100, 10, attack=attacks.hit) my_monster = Monster(100, 10, attack=attacks.bite) print(my_monster.health) # 输出100 my_hero.attack(my_monster) print(my_monster.health) # 输出90
这种方案的优势是攻击逻辑和角色完全解耦,你可以随时给角色替换不同的攻击方法,甚至新增攻击方式也不需要修改角色类。
方法3:用functools.partial绑定攻击者(更优雅的包装方式)
和方法2类似,不过用functools.partial替代lambda,代码可读性更好:
from functools import partial class Attacks: def bite(self, attacker, who): print('I bite') who.health -= attacker.strength def hit(self, attacker, who): print('I hit') who.health -= attacker.strength class Hero: def __init__(self, health, strength, attack): self.health = health self.strength = strength # 把当前角色实例绑定到攻击方法的第一个参数 self.attack = partial(attack, self) class Monster: def __init__(self, health, strength, attack): self.health = health self.strength = strength self.attack = partial(attack, self) # 测试代码 attacks = Attacks() my_hero = Hero(100, 10, attack=attacks.hit) my_monster = Monster(100, 10, attack=attacks.bite) print(my_monster.health) # 输出100 my_hero.attack(my_monster) print(my_monster.health) # 输出90
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

