写过多少Python类,就写过多少__init__:attrs让你告别样板代码
写过多少Python类,就写过多少__init__:attrs让你告别样板代码

Python里定义一个类,写完属性列表,下一步就是写__init__。不管类多简单,这步绕不开。属性少还好,一个个把参数赋值给self。属性一多,每多一个属性就多一行赋值,再配上类型注解、缩进对齐,样板代码比真正的业务逻辑还长。
attrs这个库就做一件事:把上面这些方法自动生成出来。
用起来是这样:引入define装饰器,往类上一放,属性直接声明:
from attrs import define
@define
class SomeClass:
a_number: int = 42
list_of_numbers: list[int] = []
一个装饰器,__init__、__repr__、__eq__全有了。默认值和factory模式也内置支持。
对比传统写法:一个包含5个属性的类,__init__加__repr__大概30行。同等功能用attrs,5行属性声明,其余自动处理。缩减的不是几行,是成比例的。

比dataclasses早,功能也更全
Python 3.7引入的dataclasses和attrs思路接近,但时间线上attrs在先。事实上dataclasses的作者在PEP 557里把attrs列为了参考来源。
功能层面两边有差距。attrs支持NumPy数组的相等性比较定制,dataclasses不会自动处理。对象初始化阶段插入校验逻辑,attrs的钩子机制比dataclasses的__post_init__灵活。调试时逐行步入自动生成的方法,attrs也支持。
如果你的场景简单,存几个字段、不需要额外逻辑,dataclasses够了,而且是标准库,零依赖。但需求一旦复杂,attrs多出来的灵活性就开始体现出差异了。
类型标注是可选的
attrs不强制类型标注。如果你不喜欢写类型,或者项目Python版本较早,用field()替代即可:
from attrs import define, field
@define
class SomeClass:
a_number = field(default=42)
对类型推导要求不高的项目,这个设计很实在:你不会因为引了一个库就被迫给全项目加上类型标注。
NASA火星直升机也在用
2020年起,attrs进入NASA火星直升机Ingenuity的地面软件依赖列表。代码在地外探测任务中实际运行。能推断出两点:代码质量经过了极端环境的验证;项目维护有长期承诺,不会随时中断。
维护者Hynek Schlawack同时是structlog等库的作者,社区活跃度稳定,issue响应快。
总结
attrs解决的是一个明确、具体、每个Python开发者都绕不开的问题:写类时样板代码太多。它不搞炫技,不引入新范式,用直接的方式减少重复劳动。
你如果写Python,每天和类打交道,花一个下午试试。大概率是用上了不会回去。
式,用直接的方式减少重复劳动。
你如果写Python,每天和类打交道,花一个下午试试。大概率是用上了不会回去。
更多推荐
所有评论(0)