写过多少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行属性声明,其余自动处理。缩减的不是几行,是成比例的。

README区域截图

比dataclasses早,功能也更全

Python 3.7引入的dataclassesattrs思路接近,但时间线上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,每天和类打交道,花一个下午试试。大概率是用上了不会回去。

更多推荐