类型注解
Python 的类型注解是可选的,运行时不强制校验,配合 mypy / pyright 等静态分析工具使用。
基本注解
# 变量
name: str = "Alice"
count: int = 0
ratio: float = 0.5
active: bool = True
# 函数参数与返回值
def greet(name: str, times: int = 1) -> str:
return (f"Hello, {name}!\n") * times
# 无返回值
def log(msg: str) -> None:
print(msg)typing 模块(Python 3.5–3.8)
from typing import List, Dict, Tuple, Set, Optional, Union, Any
def process(items: List[int]) -> Dict[str, int]:
return {"sum": sum(items)}
def find(lst: List[str], idx: int) -> Optional[str]:
return lst[idx] if 0 <= idx < len(lst) else None
def accept_either(val: Union[int, str]) -> str:
return str(val)
# Any 关闭类型检查
def flexible(x: Any) -> Any:
return x现代语法(Python 3.9+)
内置类型可直接用于注解,无需从 typing 导入。
# 3.9+:直接用内置类型
def process(items: list[int]) -> dict[str, int]: ...
def coords() -> tuple[float, float]: ...
def unique(items: list[str]) -> set[str]: ...
# 3.10+:使用 | 替代 Union
def parse(val: int | str) -> str:
return str(val)
# 3.10+:X | None 替代 Optional[X]
def find(key: str) -> int | None:
return NoneCallable 与高阶函数
from typing import Callable
def apply(fn: Callable[[int, int], int], a: int, b: int) -> int:
return fn(a, b)
# 参数数量不定时
def run(callback: Callable[..., None]) -> None:
callback()TypeVar — 泛型
from typing import TypeVar, Sequence
T = TypeVar("T")
def first(items: Sequence[T]) -> T:
return items[0]
first([1, 2, 3]) # int
first(["a", "b"]) # strTypeAlias
from typing import TypeAlias # 3.10+
Vector: TypeAlias = list[float]
Matrix: TypeAlias = list[list[float]]
def dot(a: Vector, b: Vector) -> float:
return sum(x * y for x, y in zip(a, b))TypedDict
from typing import TypedDict
class Movie(TypedDict):
title: str
year: int
rating: float
m: Movie = {"title": "Inception", "year": 2010, "rating": 8.8}Protocol — 结构化子类型
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
class Circle:
def draw(self) -> None:
print("○")
def render(obj: Drawable) -> None:
obj.draw()
render(Circle()) # 无需继承 Drawable,只需有 draw 方法dataclass 与类型注解
from dataclasses import dataclass, field
from typing import ClassVar
@dataclass
class Config:
host: str
port: int = 8080
tags: list[str] = field(default_factory=list)
_instance_count: ClassVar[int] = 0 # 类变量,不进入 __init__前向引用
在类体内引用自身类型时,使用字符串或 from __future__ import annotations。
from __future__ import annotations # 推迟所有注解求值(文件顶部)
class Node:
def __init__(self, val: int, next: Node | None = None):
self.val = val
self.next = next运行时访问注解
def add(a: int, b: int) -> int:
return a + b
import inspect
sig = inspect.signature(add)
for name, param in sig.parameters.items():
print(name, param.annotation)
add.__annotations__ # {'a': int, 'b': int, 'return': int}类型检查工具
# mypy:成熟的静态类型检查器
pip install mypy
mypy script.py
# pyright / pylance:微软出品,VS Code 内置
pip install pyright
pyright script.py
# pydantic:运行时验证(常用于 API 和配置)
pip install pydanticfrom pydantic import BaseModel, Field
class User(BaseModel):
name: str
age: int = Field(gt=0, le=150)
email: str
u = User(name="Alice", age=30, email="alice@example.com")
u.model_dump() # {'name': 'Alice', 'age': 30, 'email': '...'}