pydantic学习与使用-5.dataclasses 数据类的学习使用

前言

python3.7 的新特性 dataclass,dataclass是指“一个带有默认值的可变的namedtuple”,广义的定义就是有一个类,它的属性均可公开访问。

dataclass简介

dataclass 的属性可以带有默认值并能被修改,而且类中含有与这些属性相关的类方法,那么这个类就可以称为dataclass,
再通俗点讲,dataclass就是一个含有数据及操作数据方法的容器。

  • 相比普通class,dataclass通常不包含私有属性,数据可以直接访问
  • dataclass的repr方法通常有固定格式,会打印出类型名以及属性名和它的值
  • dataclass拥有__eq__和__hash__魔法方法
  • dataclass有着模式单一固定的构造方式,或是需要重载运算符,而普通class通常无需这些工作

如果用的python3.6版本,需先安装dataclasses模块,python3.7以上版本已经自带了

pip install dataclasses==0.8

如果已经安装过pydantic包,dataclasses模块就已经一起装好了。

简单示例

dataclasses 数据类简单示例

from dataclasses import dataclass
from typing import List


@dataclass
class User:
    """用户数据类"""
    name: str
    age: int
    friends: List[int]


user = User(name="yo yo", age=20, friends=[2, 3, 4])
print(user)  # User(name='yo yo', age=20, friends=[2, 3, 4])
print(user.name)  # yo yo
print(user.age)   # 20
print(user.friends)  # [2, 3, 4]

dataclass 继承的使用, 可以把前面的User 当成一个父类,子类继承后可以覆盖父类的属性

from dataclasses import dataclass
from typing import List


@dataclass
class User:
    """用户数据类"""
    name: str
    age: int
    friends: List[int]


@dataclass
class Sun(User):
    """子类"""
    name: str
    age: str
    friends: List[int]


a = Sun(name='yo', age='22', friends=[])
print(a)

pydantic 中使用 dataclasses

如果您不想使用pydantic 的 BaseModel 模块,您可以在标准数据类上获得相同的数据验证(在 python 3.7 中引入)。
数据类在 python 3.6 中需下载第三方包 dataclasses 工作。

from datetime import datetime
from pydantic.dataclasses import dataclass


@dataclass
class User:
    id: int
    name: str = 'John Doe'
    signup_ts: datetime = None


user = User(id='42', signup_ts='2032-06-21T12:00')
print(user)
#> User(id=42, name='John Doe', signup_ts=datetime.datetime(2032, 6, 21, 12, 0))

pydantic.dataclasses.dataclassdataclasses.dataclass with validation 的替代品, 而不是pydantic.BaseModel 的替代品(在初始化挂钩的工作方式上有一点不同)
在某些情况下,将pydanticis.BaseModel子类化是更好的选择.

您可以使用所有标准的 pydantic 字段类型,生成的数据类将与标准库 dataclass 装饰器创建的数据类相同。

可以通过 访问底层模型及其模式__pydantic_model__。此外,需要 a 的字段default_factory可以由 a 指定dataclasses.field

import dataclasses
from typing import List, Optional

from pydantic import Field
from pydantic.dataclasses import dataclass


@dataclass
class User:
    id: int
    name: str = 'John Doe'
    friends: List[int] = dataclasses.field(default_factory=lambda: [0])
    age: Optional[int] = dataclasses.field(
        default=None,
        metadata=dict(title='The age of the user', description='do not lie!')
    )
    height: Optional[int] = Field(None, title='The height in cm', ge=50, le=300)


user = User(id='42')
print(user.__pydantic_model__.schema())
"""
{
    'title': 'User',
    'type': 'object',
    'properties': {
        'id': {'title': 'Id', 'type': 'integer'},
        'name': {
            'title': 'Name',
            'default': 'John Doe',
            'type': 'string',
        },
        'friends': {
            'title': 'Friends',
            'type': 'array',
            'items': {'type': 'integer'},
        },
        'age': {
            'title': 'The age of the user',
            'description': 'do not lie!',
            'type': 'integer',
        },
        'height': {
            'title': 'The height in cm',
            'minimum': 50,
            'maximum': 300,
            'type': 'integer',
        },
    },
    'required': ['id'],
}
"""

pydantic.dataclasses.dataclass的参数与标准装饰器相同,除了一个额外的关键字参数config与Config具有相同的含义。

嵌套数据类

数据类和普通模型都支持嵌套数据类。

from pydantic import AnyUrl
from pydantic.dataclasses import dataclass


@dataclass
class NavbarButton:
    href: AnyUrl


@dataclass
class Navbar:
    button: NavbarButton


navbar = Navbar(button=('https://example.com',))
print(navbar)
#> Navbar(button=NavbarButton(href=AnyUrl('https://example.com', scheme='https',
#> host='example.com', tld='com', host_type='domain')))

json 转储

Pydantic数据类没有.json()功能。要将它们转储为 JSON,您需要使用pydantic_encoder以下内容:

import dataclasses
import json
from typing import List

from pydantic.dataclasses import dataclass
from pydantic.json import pydantic_encoder


@dataclass
class User:
    id: int
    name: str = 'John Doe'
    friends: List[int] = dataclasses.field(default_factory=lambda: [0])


user = User(id='42')
print(json.dumps(user, indent=4, default=pydantic_encoder))
"""
{
    "id": 42,
    "name": "John Doe",
    "friends": [
        0
    ]
}
"""
posted @ 2022-02-21 11:08  上海-悠悠  阅读(1021)  评论(0编辑  收藏  举报