使用attrs.Converter触发mypy错误:仅支持命名函数、类型与lambda
解决 attrs 转换器引发的 mypy 类型检查错误
问题背景
编写 attrs 类时,使用 attrs.Converter 对象作为字段转换器,触发 mypy 错误:
Unsupported converter, only named functions, types and lambdas are currently supported
相关代码:
import attrs from attrs import define, field def complicated(value, self_, field): return int(value) * self_.factor + field.metadata["offset"] @define class C: factor = 5 # 非 attrs 字段 x = field( metadata={"offset": 200}, converter=attrs.Converter( complicated, takes_self=True, takes_field=True )) C("42") C(x=410)
问题原因
mypy 的 attrs 类型检查插件暂不支持直接传入 attrs.Converter 实例作为转换器参数,仅识别命名函数、类型、lambda 表达式这几类转换器形式。
解决方案
方案1:用 lambda 封装转换器逻辑
直接用 lambda 表达式包裹原转换器函数,传递所需的 self 和 field 参数,适配 mypy 的检查规则:
import attrs from attrs import define, field def complicated(value, self_, field): return int(value) * self_.factor + field.metadata["offset"] @define class C: factor = 5 # 非 attrs 字段 x = field( metadata={"offset": 200}, converter=lambda v, self=self, fld=field: complicated(v, self, fld) ) # 测试正常运行 C("42") C(x=410)
方案2:通过闭包生成转换器
如果逻辑更复杂,可通过闭包提前绑定 self 和 field,生成符合要求的转换器函数:
import attrs from attrs import define, field def make_converter(self, field): def converter(value): return int(value) * self.factor + field.metadata["offset"] return converter @define class C: factor = 5 # 非 attrs 字段 x = field( metadata={"offset": 200}, converter=lambda v, self=self, fld=field: make_converter(self, fld)(v) )
方案3:将非 attrs 字段转为 attrs 字段(推荐)
把 factor 改为 attrs 字段(设置 init=False 避免参与初始化),这样可以更自然地在转换器中访问实例属性,同时完美兼容 mypy:
import attrs from attrs import define, field @define class C: factor = field(default=5, init=False) # 转为 attrs 内部字段 x = field( metadata={"offset": 200}, converter=lambda v, self=self: int(v) * self.factor + self.x.metadata["offset"] ) # 测试正常运行 C("42") C(x=410)
内容的提问来源于stack exchange,提问作者Sebastian Souza Tarnowski
相关产品推荐
相关产品推荐

