flyfish
在 Python 编程里,type hints(类型提示)是一项关键特性,它能为变量、函数参数、返回值等添加类型注解,从而提升代码的可读性
int
、str
、list
、自定义类等都属于数据类型。# 不使用类型提示
def add(a, b):
return a + b
# 使用类型提示
def add(a: int, b: int) -> int:
return a + b
name: str = "Alice" # 字符串类型
age: int = 30 # 整数类型
is_student: bool = True # 布尔类型
def greet(name: str) -> str:
return f"Hello, {name}"
def calculate_total(prices: list[float]) -> float:
return sum(prices)
typing
模块)from typing import List, Dict, Optional, Union
# 列表元素类型为字符串
names: List[str] = ["Alice", "Bob"]
# 字典键为字符串,值为整数
person: Dict[str, int] = {"age": 30, "score": 95}
# 可选类型(可以是字符串或者 None)
address: Optional[str] = None
# 联合类型(可以是整数或者浮点数)
number: Union[int, float] = 3.14
class Point:
def __init__(self, x: float, y: float):
self.x = x
self.y = y
def distance(p1: Point, p2: Point) -> float:
return ((p1.x - p2.x) ** 2 + (p1.y - p2.y) ** 2) ** 0.5
from typing import TypeVar, List
T = TypeVar('T') # 定义泛型类型
def first_element(items: List[T]) -> T | None:
return items[0] if items else None
# 类型别名
Vector = List[float]
def scale(vector: Vector, factor: float) -> Vector:
return [x * factor for x in vector]
Pydantic 以类型提示为基础进行数据验证,两者结合使用能发挥强大的威力:
from pydantic import BaseModel
from typing import List, Optional
class Book(BaseModel):
title: str
author: str
year: int
tags: Optional[List[str]] = [] # 可选的字符串列表
# 自动验证类型
book = Book(title="Python Crash Course", author="Eric Matthes", year=2015)
# 类型错误会引发验证异常
try:
Book(title=123, author="Invalid", year="2023")
except ValueError as e:
print(e) # 输出: "title" 应该是字符串类型,"year" 应该是整数类型
def process_data(data: dict[str, list[int]]) -> tuple[float, float]:
"""处理数据并返回平均值和最大值"""
values = [item for sublist in data.values() for item in sublist]
return sum(values)/len(values), max(values)
class User:
name: str
age: int
hobbies: list[str]
def __init__(self, name: str, age: int, hobbies: list[str]):
self.name = name
self.age = age
self.hobbies = hobbies
students: list[dict[str, str | int]] = [
{"name": "Alice", "age": 20},
{"name": "Bob", "age": 22}
]
Python 是动态类型语言,类型提示不会影响程序的运行,只是起到辅助作用。
类型提示在运行时会被忽略,若需要强制类型检查,可借助 Pydantic 等工具。
Python 3.9 及以后的版本可以直接使用内置的容器类型(如 list
、dict
),无需从 typing
模块导入。
BaseModel
的核心功能之一就是通过 Python 类型提示(Type Hints) 来定义和验证数据结构。不过,它的功能远不止于此。
Field
设置最小值、最大值、长度限制等。@validator
装饰器编写复杂逻辑。from pydantic import BaseModel, Field, validator
class User(BaseModel):
id: int
name: str = Field(min_length=2, max_length=50)
age: int = Field(ge=0, le=150) # 年龄范围 0-150
@validator('name')
def validate_name(cls, v):
if v.isdigit():
raise ValueError('名字不能全为数字')
return v
model.dict()
或 model.json()
导出数据。Model(**data)
或 Model.parse_obj(data)
导入数据。class Address(BaseModel):
city: str
street: str
class UserWithAddress(BaseModel):
name: str
address: Address
# 嵌套数据反序列化
user = UserWithAddress.parse_obj({
"name": "Alice",
"address": {"city": "Beijing", "street": "Main St"}
})
# 序列化
print(user.json(indent=2))
Config
类自定义模型行为:
extra = 'forbid'
:禁止额外字段。validate_assignment = True
:赋值时验证(动态修改字段时触发验证)。orm_mode = True
:支持从 ORM 对象创建模型。class Settings(BaseModel):
api_key: str
debug: bool = False
class Config:
env_file = ".env" # 从环境变量加载
allow_mutation = False # 禁止修改字段
ValidationError
,包含错误位置和原因。try:
User(id="invalid", name="A", age=-5)
except ValidationError as e:
print(e.json(indent=2))
"""输出:
[
{
"loc": ["id"],
"msg": "value is not a valid integer",
"type": "type_error.integer"
},
...
]
"""
None
或 Optional
定义可选字段。Field(default_factory)
设置动态默认值(如生成唯一 ID)。from uuid import UUID, uuid4
from typing import Optional
class Item(BaseModel):
id: UUID = Field(default_factory=uuid4) # 自动生成 UUID
name: str
description: Optional[str] = None # 可选字段
@property
装饰器定义只读字段。@computed_field
(Pydantic v2)定义更灵活的计算字段。class Rectangle(BaseModel):
width: float
height: float
@property
def area(self) -> float:
return self.width * self.height
Union
或 discriminator
实现多态。from typing import Union
class Animal(BaseModel):
name: str
class Dog(Animal):
breed: str
class Cat(Animal):
is_indoor: bool
class Zoo(BaseModel):
animals: list[Union[Dog, Cat]] # 支持多种动物类型