两层继承结构中类属性重写失效问题及解决方法
问题根源与解决方案
没错,你猜的完全正确——问题就出在Treasure类的pile_setup方法里直接硬编码引用了Card.pile_player_rate!
为什么会出现这个问题?
你用了@staticmethod装饰器,静态方法是类的“无绑定工具方法”,它不会自动关联调用它的子类上下文。当你调用Copper.pile_setup(6)时,静态方法内部还是只会去Card类里找属性值,完全无视Copper重写的pile_player_rate。
怎么修复这个问题?
把静态方法改成类方法(用@classmethod装饰器),类方法会自动接收一个cls参数,这个参数就是调用该方法的实际类(比如你调用Copper.pile_setup时,cls就指向Copper类)。这样就能动态获取当前类的属性值了。
修改后的代码示例:
Card类(无需改动)
class Card: normal_full_table = 6 pile_player_rate = 10 @staticmethod def pile_setup(player_count): pass
Treasure类(改为类方法)
from card.card import Card from math import floor class Treasure(Card): @classmethod def pile_setup(cls, player_count): # 用cls代替Card,动态获取当前调用类的属性 return (floor(player_count / cls.normal_full_table) + 1) * cls.pile_player_rate
Copper类(无需改动)
from card.basic.card_treasure import Treasure class Copper(Treasure): pile_player_rate = 60
现在测试调用:
print(Copper.pile_setup(6)) # 计算结果:(6//6 +1)*60 = 120,完全符合预期
额外拓展
如果Treasure类本身需要专属的pile_player_rate,直接在Treasure里定义即可,类方法会自动优先使用当前类的属性:
class Treasure(Card): pile_player_rate = 20 # 新增Treasure自己的属性 @classmethod def pile_setup(cls, player_count): return (floor(player_count / cls.normal_full_table) + 1) * cls.pile_player_rate
此时调用Treasure.pile_setup(6)会得到(1+1)*20=40,调用Copper.pile_setup(6)依然会使用Copper的60,完美实现属性的多态复用。
内容的提问来源于stack exchange,提问作者neogeek23
相关产品推荐
相关产品推荐

