精通 Python Attrs:构建高级数据类的实战指南
attrs 包让你用简洁注解创建高级数据类。Python 原生 dataclass 固然好用,但 attrs 提供额外进阶特性。
目录
安装 attrs
attrs 非标准库,需 pip install attrs 或 pipenv install attrs。建议虚拟环境隔离。
$ pip install attrs # or with pipenv: $ pipenv install attrs
attrs vs 原生数据类
attrs 作者参与了引入数据类的 PEP。原生数据类有意保持简洁易懂,而 attrs 提供全功能集。
选 attrs 而非原生数据类的理由:
- Python <3.7:attrs 支持主流版本含 CPython 2.7、PyPy。
- 需更多特性:验证器、转换器。
- 追求极致性能与最小内存:attrs 支持 slotted 类。
基础 attrs 示例
import attr
@attr.s
class Person(object):
name = attr.ib(default='John')
surname = attr.ib(default='Doe')
age = attr.ib(init=False)
p = Person()
print(p)
p = Person('Bill', 'Gates')
p.age = 60
print(p)
# Output:
# Person(name='John', surname='Doe', age=NOTHING)
# Person(name='Bill', surname='Gates', age=60)
观察:
• 语法比数据类啰嗦,但换回额外特性。
• 打印自动格式化,利于调试。
• attr.ib 等短名开箱即用,亦可 from attr import attrib, attrs 用全名,功能等价。
attrs 验证器示例
两种添加验证器方式:
1. 装饰器
2. 传入可调用对象
先演示可调用对象法。attrs 内置多种验证器,示例用 instance_of:
>>> @attr.s
... class C(object):
... x = attr.ib(validator=attr.validators.instance_of(int))
>>> C(42)
C(x=42)
>>> C("a string")
Traceback (most recent call last):
...
TypeError: ("'x' must be <type 'int'> (got 'a string' that is a <type 'str'>).", ...
传字符串给 x,instance_of 抛错要求 int。
自定义验证器:
import attr
@attr.s
class DividableByTwo(object):
x = attr.ib()
@x.validator
def check(self, attribute, value):
if value % 2 != 0:
raise ValueError(f'{value} is not dividable by 2')
print(DividableByTwo(60))
print(DividableByTwo(11))
# Output:
# DividableByTwo(x=60)
# ...
# ValueError: 11 is not dividable by 2
attrs 转换器示例
转换器在赋值前自动转换值。用途广泛。示例:自动转 int。用可调用 int():
import attr
@attr.s
class C(object):
x = attr.ib(converter=int)
c = C("1")
print(c)
# Output:
# C(x=1)
输入字符串 "1" 自动转整数。转换器先于验证器运行,故可先转型再验证。如结合上两例:先转 int,再验证能否被 2 整除。
attrs 结合 slots
可指示 attrs 生成 slotted 类。slotted 类优势:
• 内存占用更小
• 速度更快
本质:显式声明实例属性,Python 省去部分检查,节省内存、提速。详见 attrs 文档。
手写 slotted 类有坑,attrs 一行搞定:
import attr
@attr.s(slots=True)
class YourClassName:
...
持续学习
- 本站《Python 数据类》文章
- 本站《Python 类与对象》教程
attrs官方示例页
Python
- 以强大分析赋能高端制造决策:从描述到处方的进阶之路
- 精通Python数据类型:实战指南
- Python strip() 方法完全指南:去除首尾空白与自定义字符实战
- Python str.count() 完全指南:统计字符与子串出现次数实战
- Python round() 函数详解与实战示例
- 精通 Python map() 函数:语法、示例与最佳实践
- Python timeit():精准测量代码执行时间与实战示例
- Python collections.Counter:高效计数、更新与算术运算
- Python time.sleep():为代码添加延迟的完整指南
- Python list.count() 专家指南:语法、示例与性能解析
- Python list.index() 详解:查找元素位置的实用指南与示例
- Python C 扩展开发指南:构建高性能原生模块