Hypothesis构建int子类实例报错:TypeError问题求解
解决Hypothesis无法构建FixedUint子类实例的问题
问题根源
int是不可变类型,它的实例创建逻辑由__new__方法控制,而非__init__。你的FixedUint重写了__init__并添加了value参数,但int.__init__不接受value关键字参数——Hypothesis默认会用关键字参数传递构造参数,导致U64(value=xxx)调用触发TypeError。
方案一:将验证逻辑移至__new__方法
这是子类化不可变类型的标准做法,直接在实例创建阶段完成验证,同时避免关键字参数冲突:
from typing import ClassVar, TypeVar from hypothesis import strategies as st T = TypeVar("T", bound="FixedUint") class FixedUint(int): MAX_VALUE: ClassVar["FixedUint"] def __new__(cls: type[T], value: int) -> T: # 先验证输入合法性 if not isinstance(value, int): raise TypeError("值必须为整数") if value < 0 or value > cls.MAX_VALUE: raise OverflowError(f"值 {value} 超出范围 [0, {cls.MAX_VALUE}]") # 调用父类__new__创建实例,用位置参数传递value return super().__new__(cls, value) class U256(FixedUint): MAX_VALUE: ClassVar[U256] = U256(2**256 - 1) class U64(FixedUint): MAX_VALUE: ClassVar[U64] = U64(2**64 - 1) # 现在可以正常生成实例 print(st.from_type(U64).example())
关键说明
- 不可变类型的实例初始化逻辑必须放在
__new__中,因为__init__是在实例已经创建后才执行的,此时修改属性没有意义。 - 调用
super().__new__(cls, value)时使用位置参数,完全符合int的构造规则,不会触发关键字参数错误。
方案二:注册Hypothesis自定义策略(无需修改类结构)
如果无法改动原有FixedUint的代码,可以给Hypothesis注册针对U64/U256的生成策略,绕过构造函数的参数问题:
# 在原有代码基础上添加以下注册逻辑 st.register_type_strategy( U64, st.integers(min_value=0, max_value=U64.MAX_VALUE).map(U64) ) st.register_type_strategy( U256, st.integers(min_value=0, max_value=U256.MAX_VALUE).map(U256) ) # 验证生成 print(st.from_type(U64).example())
关键说明
- 该策略先生成合法范围内的整数,再通过
map转换为U64/U256实例,避免了Hypothesis用关键字参数调用构造函数的行为。 - 适合无法修改原有类定义的场景,快速适配Hypothesis的生成逻辑。
内容的提问来源于stack exchange,提问作者ClementWalter
相关产品推荐
相关产品推荐

