Python 类初始化时如何创建依赖其他参数的派生属性
报错根源
你遇到的type object 'Enemy' has no attribute 'head'报错,本质是没搞清楚类属性和实例属性的访问时机:
- 写在
__init__构造方法里、通过self.xxx = 值定义的属性,全是实例属性。只有当你用类真正生成一个具体的敌人对象(比如造出这个骷髅)时,这些属性才会被绑定到对象上。作为模板的Enemy类本身,从代码定义完成到运行结束都不会自带这些属性,所以你在实例化时写Enemy.head去访问类的对应字段,必然会提示类没有这个属性。 - 你之前试
self.head算值失败,是因为这部分计算代码被放到了类定义的外面;你试skeleton.head算值失败,是因为参数是按位置顺序传入的——代码执行到要算总护甲的位置时,前面的装备参数还没完成赋值,自然读不到对应的值。
派生属性的实现方法
针对总护甲、最终伤害这种完全靠装备值自动计算的派生属性,新手最容易上手的写法,是把计算逻辑直接挪到__init__方法内部:
- 删掉原本需要手动传入的
armor、damage参数——这两个值本来就该靠装备自动算,手动传不仅麻烦还容易写错 - 在方法内部拿到各部位装备、武器的引用后,直接计算总护甲、最终伤害,赋值给实例的对应属性
- 实例化的时候只需要传入固定的基础参数就行
修正后的代码参考:
class Enemy: def __init__(self, name, health, maxhealth, head, torso, legs, feet, weapon, gold): self.name = name self.health = health self.maxhealth = maxhealth # 绑定各部位装备 self.head = head self.torso = torso self.legs = legs self.feet = feet # 自动计算总护甲,不需要手动传值 self.armor = head["defense"] + torso["defense"] + legs["defense"] + feet["defense"] self.weapon = weapon # 自动计算最终伤害,不需要手动传值 self.damage = 1 + weapon["damage"] self.gold = gold # 实例化骷髅时仅传固定基础值,无需手动计算派生属性 skeleton = Enemy( "Skeleton", 60, 60, armors["leatherhelm"], armors["leathertorso"], armors["leatherleggings"], armors["leatherboots"], weapons["rustycutlass"], 33 )
括号书写说明
你习惯把每个参数单独换行的写法完全符合Python语法,没有任何问题,只要保证圆括号匹配、参数顺序和构造函数的定义一一对应即可,不需要强行把所有参数挤到单行。
内容的提问来源于stack exchange,提问作者namu
相关产品推荐
相关产品推荐

