You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

子类初始化触发AttributeError,如何解决自定义数值类型初始化问题?

问题分析与解决

你踩的核心坑是搞混了类定义阶段和实例化阶段的逻辑:__init_subclass__是在子类(比如Bar)被定义时就执行的,这时候Bar类本身根本没有first、second这些属性——这些是你要给实例用的,不是类属性。所以你在__init_subclass__里硬要获取类的first属性,自然会触发AttributeError。

正确实现思路

  1. 用__init_subclass__收集子类的类型注解,存到类的专属属性里(比如_field_types),不用直接去拿属性值。
  2. 在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 10:35:03