子类初始化触发AttributeError,如何解决自定义数值类型初始化问题?
问题分析与解决
你踩的核心坑是搞混了类定义阶段和实例化阶段的逻辑:__init_subclass__是在子类(比如Bar)被定义时就执行的,这时候Bar类本身根本没有first、second这些属性——这些是你要给实例用的,不是类属性。所以你在__init_subclass__里硬要获取类的first属性,自然会触发AttributeError。
正确实现思路
- 用
__init_subclass__收集子类的类型注解,存到类的专属属性里(比如_field_types),不用直接去拿属性值。 - 在Foo的
__init__方法里,根据收集到的注解,处理传入的参数,转换成对应的Number子类实例,再绑定到实例上。
示例代码
class Number: pass class uint16_t(Number): def __init__(self, value): # 可选:添加范围校验,比如0-65535 self.value = value class uint32_t(Number): def __init__(self, value): # 可选:添加范围校验,比如0-4294967295 self.value = value class Foo: def __init_subclass__(cls): # 收集子类的类型注解,存在类的_field_types属性中 cls._field_types = {} for name, type_cls in cls.__annotations__.items(): if issubclass(type_cls, Number): cls._field_types[name] = type_cls def __init__(self, **kwargs): # 实例化阶段处理参数,绑定为实例属性 for field_name, type_cls in self._field_types.items(): raw_value = kwargs.get(field_name) if raw_value is None: raise ValueError(f"缺少必填字段: {field_name}") # 转换为对应的Number子类实例 setattr(self, field_name, type_cls(raw_value)) class Bar(Foo): first: uint32_t second: uint16_t # 测试实例化 b = Bar(first=10, second=5) print(b.first.value) # 输出10 print(b.second.value) # 输出5
关键说明
__init_subclass__只负责收集规则(哪些字段需要用什么类型处理),不碰具体属性值——类定义阶段本来就没有实例值。- 实际的属性赋值、类型转换要放到
__init__里做,这才是实例化时该干的事。 - 如果你原来想在
__init_subclass__里绑定属性,那完全找错了地方,类级属性和实例属性是两回事。
内容的提问来源于stack exchange,提问作者roman
相关产品推荐
相关产品推荐

