装饰器能否在__init_subclass__调用前修改子类实现注册表关联?
解决装饰器与__init_subclass__执行顺序冲突的方案
你遇到的核心问题是Python类定义时的执行顺序:子类继承父类时会先触发父类的__init_subclass__,之后才会应用装饰器修改子类属性。要通过装饰器实现注册表关联,有两种可行思路:
思路一:将注册逻辑移至装饰器,弱化__init_subclass__的即时检查
直接把原本在__init_subclass__里的注册逻辑放到装饰器中执行,__init_subclass__只做基础标记或留空,避免强制检查导致的异常。
class Registry: # 注册表存储子类的字典 _registered_classes = {} @classmethod def link(cls, subclass): # 给子类绑定注册表实例 subclass._registry = cls() # 执行注册逻辑:将子类存入注册表 cls._registered_classes[subclass.__name__] = subclass return subclass class Foo: _registry = None def __init_subclass__(cls): # 这里不再强制检查_registry,仅做可选的初始化操作 pass # 用法示例 @Registry.link class Bar(Foo): pass @Registry.link class Baz(Foo): pass # 验证注册结果 print(Registry._registered_classes) # 输出:{'Bar': <class '__main__.Bar'>, 'Baz': <class '__main__.Baz'>}
思路二:用装饰器动态生成带预设置注册表的子类
通过装饰器创建一个继承原子类的中间类,预先设置好_registry,再触发父类的__init_subclass__,这样就能保证检查时_registry已存在。
class Registry: _registered_classes = {} @classmethod def link(cls, base_cls): # 生成中间类,预先绑定注册表实例 class LinkedSubclass(base_cls): _registry = cls() return LinkedSubclass class Foo: _registry = None def __init_subclass__(cls): # 保留原有的检查逻辑 if cls._registry is None: raise ValueError("子类必须通过Registry.link关联注册表") # 执行注册逻辑 cls._registry._registered_classes[cls.__name__] = cls # 用法示例 @Registry.link class Bar(Foo): pass # 验证注册结果 print(Registry._registered_classes) # 输出:{'Bar': <class '__main__.LinkedSubclass'>}
这种方案的核心是调整了执行顺序:装饰器先创建带_registry的中间类,再触发父类的__init_subclass__,此时检查条件已满足。
内容的提问来源于stack exchange,提问作者CyDevos
相关产品推荐
相关产品推荐

