前言
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.dataclass
是dataclasses.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
]
}
"""