简述

在 Python 编程中,一些类用于存储数据,称为“数据类”,如商品模型。

attrs 是 Hynek Schlawack 设计的库,用于简化数据类定义。

dataclasses 是 Python 3.7 标准库模块,类似 attrs。

数据类的痛点

数据类常需实现:

  • __init__ 初始化参数;
  • __repr__ 表示对象;
  • __eq__ 和比较方法;
  • __hash__ 用于去重;
  • to_dict 或 to_json 方法打包属性。

这些实现繁琐,希望有便捷方式定义参数和方法。

attrs

安装

pip install attrs

基本使用

import attr

@attr.s(hash=True)
class Product:
    id = attr.ib()
    author_id = attr.ib()
    brand_id = attr.ib()
    spu_id = attr.ib()
    title = attr.ib(repr=False, cmp=False, hash=False)
    item_id = attr.ib(repr=False, cmp=False, hash=False)
    n_comments = attr.ib(repr=False, cmp=False, hash=False)
    creation_time = attr.ib(repr=False, cmp=False, hash=False)
    update_time = attr.ib(repr=False, cmp=False, hash=False)
    source = attr.ib(default='', repr=False, cmp=False, hash=False)
    parent_id = attr.ib(default=0, repr=False, cmp=False, hash=False)
    ancestor_id = attr.ib(default=0, repr=False, cmp=False, hash=False)

@attr.s 设置全局选项,默认参数参与 repr、cmp、init,不参与 hash。

attr.ib 设置字段选项,优先级高。

示例中,所有字段在 init,前 4 个参与 repr、cmp、hash,后 3 个有默认值。

字段类型验证

用装饰器添加验证:

import attr

@attr.s
class C:
    x = attr.ib()

    @x.validator
    def check(self, attribute, value):
        if value > 42:
            raise ValueError("x must be <= 42")

或用 validator 参数:

def x_smaller_than_y(instance, attribute, value):
    if value >= instance.y:
        raise ValueError("'x' must be < 'y'")

@attr.s
class C:
    x = attr.ib(validator=[attr.validators.instance_of(int), x_smaller_than_y])
    y = attr.ib()

先验证 x 为 int,再 x < y。

属性类型转化

自动转化类型:

import attr

@attr.s
class C:
    x = attr.ib(converter=int)

传入 x 自动转为 int。

包含元数据

字段可含元数据:

@attr.s
class C:
    x = attr.ib(metadata={'my_metadata': 1})

# 访问
attr.fields(C).x.metadata['my_metadata']  # 1

dataclasses

Python 3.7 新增,基于 PEP 557。Python 3.6 可 pip 安装。

示例:

from dataclasses import dataclass, field
from datetime import datetime

@dataclass(hash=True, order=True)
class Product:
    id: int
    author_id: int
    brand_id: int
    spu_id: int
    title: str = field(hash=False, repr=False, compare=False)
    item_id: int = field(hash=False, repr=False, compare=False)
    n_comments: int = field(hash=False, repr=False, compare=False)
    creation_time: datetime = field(default=None, repr=False, compare=False, hash=False)
    update_time: datetime = field(default=None, repr=False, compare=False, hash=False)
    source: str = field(default='', repr=False, compare=False, hash=False)
    parent_id: int = field(default=0, repr=False, compare=False, hash=False)
    ancestor_id: int = field(default=0, repr=False, compare=False, hash=False)

@dataclass 全局设置,默认参与 init、repr、eq,不参与 order、unsafe_hash。

field 设置字段选项。

用 type annotations 验证类型。

参考链接