使用typing增强Python代码的可读性、可维护性,并帮助静态分析工具进行错误检查。
Python 的 typing 模块是用于 类型注解和静态类型检查 的标准库工具。它为你编写类型安全、可读性强的大型代码提供了支持。
 基础类型和泛型容器类型
基础类型注解
| 1
 | int, float, str, bool, bytes
 | 
泛型容器类型
| 类型 | 用法示例 | 
| List | List[int] — 整数列表 | 
| Dict | Dict[str, float] — 键为字符串,值为浮点数 | 
| Tuple | Tuple[int, str] — 二元组 | 
| Set | Set[int] | 
| FrozenSet | FrozenSet[str] | 
- Python 3.9+ 支持原生写法,如 list[int]替代List[int]。
 例如:
| 12
 3
 4
 5
 6
 
 | from typing import List
 def average(scores: List[float]) -> float:
 return sum(scores) / len(scores)
 
 print(average([90.0, 85.5, 78.0]))
 
 | 
| 12
 3
 4
 5
 6
 7
 
 | from typing import Dict
 def get_student_score(name: str, records: Dict[str, float]) -> float:
 return records[name]
 
 data = {"Alice": 91.5, "Bob": 88.0}
 print(get_student_score("Alice", data))
 
 | 
| 12
 3
 4
 5
 6
 7
 
 | from typing import Tuple
 def get_student_info() -> Tuple[str, int]:
 return ("Alice", 20)
 
 name, age = get_student_info()
 print(name, age)
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 
 | from typing import Dict, List
 def total_scores(data: Dict[str, List[int]]) -> Dict[str, int]:
 return {name: sum(scores) for name, scores in data.items()}
 
 records = {
 "Alice": [90, 85, 92],
 "Bob": [78, 80, 74]
 }
 print(total_scores(records))
 
 | 
 通用类型工具
| 工具 | 描述 | 
| Any | 任意类型 | 
| Union | 多种类型之一,例如 Union[int, str] | 
| Optional | 可以是某种类型或 None,等价于 Union[T, None] | 
| Callable | 函数类型,例如 Callable[[int, int], str] 表示接受两个 int 返回 str 的函数 | 
| Literal | 指定字面值,例如 Literal[‘yes’, ‘no’] | 
| TypeVar | 泛型类型变量(定义泛型函数或类时使用) | 
| Generic | 创建自定义泛型类时用 | 
| Final | 声明不能被重写或赋值的变量/属性 | 
| ClassVar | 用于声明类变量,而非实例变量 | 
| 例如: |  | 
 TypeVar
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | from typing import TypeVar, Tuple
 T = TypeVar('T')
 
 def swap(a: T, b: T) -> Tuple[T, T]:
 return b, a
 
 print(swap(1, 2))
 print(swap("hi", "bye"))
 
 | 
- T 可以是任何类型(int、str、float…)
 Generic
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | from typing import TypeVar, Generic
 T = TypeVar('T')
 
 class Box(Generic[T]):
 def __init__(self, content: T):
 self.content = content
 
 def get(self) -> T:
 return self.content
 
 int_box = Box
 print(int_box.get())
 
 str_box = Box[str]("hello")
 print(str_box.get())
 
 | 
- Box[T]表示这是一个“存放任意类型 T 的盒子”
- Generic[T]表示类是“泛型类”
 Any
| 12
 3
 4
 5
 6
 7
 8
 
 | from typing import Any
 def print_anything(x: Any) -> None:
 print(f"Received: {x}")
 
 print_anything(42)
 print_anything("hello")
 print_anything([1, 2, 3])
 
 | 
 结构化和协议
| 类型 | 描述 | 
| Protocol | 定义接口或行为协议(Python 3.8+) | 
| TypedDict | 类似 dict 的结构化类型注解 | 
| NamedTuple | 类型注解版本的命名元组 | 
| dataclass | 与 @dataclass 一起使用可以加注解 | 
| 例如: |  | 
 TypedDict
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | from typing import TypedDict
 class User(TypedDict):
 id: int
 name: str
 is_active: bool
 
 def greet(user: User) -> str:
 return f"Hello, {user['name']}!"
 
 u = {"id": 1, "name": "Alice", "is_active": True}
 print(greet(u))
 
 | 
- 明确了 user 必须包含哪些字段
- 静态检查工具(如 mypy)可以发现拼写错误或字段缺失
 Protocol
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | from typing import Protocol
 class Reader(Protocol):
 def read(self) -> str:
 ...
 
 class FileReader:
 def read(self) -> str:
 return "data from file"
 
 class Dummy:
 def read(self) -> str:
 return "test data"
 
 def load(r: Reader) -> str:
 return r.read()
 
 print(load(FileReader()))
 print(load(Dummy()))
 
 | 
当你只关心某个对象是否有某些方法或属性(而不是它的具体类型),使用 Protocol 可以定义“接口”,实现 Python 的“结构子类型检查”。
- load() 不关心对象的真实类型,只要有 .read() 方法就行
- 非侵入式,“只要像鸭子,它就能飞”(典型的 duck typing)
 dataclasses
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | from dataclasses import dataclass
 @dataclass
 class User:
 id: int
 name: str
 is_active: bool = True
 
 
 u = User(id=1, name="Alice")
 print(u)
 
 | 
- 自动生成了 init() 方法
- 自动实现了 repr() 和 eq() 等方法
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | from dataclasses import dataclass
 @dataclass(order=True)
 class Product:
 price: float
 name: str
 
 p1 = Product(19.9, "A")
 p2 = Product(29.9, "B")
 
 print(p1 < p2)
 
 | 
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | from dataclasses import dataclass, field
 @dataclass
 class Token:
 value: str
 secret: str = field(repr=False, compare=False)
 
 t1 = Token("abc", "secret123")
 print(t1)
 
 | 
忽略某个字段:field(repr=False, compare=False, default=…)
 特殊类型工具
| 类型 | 描述 | 
| NewType | 定义新的类型别名,例如:UserId = NewType(‘UserId’, int) | 
| Type | 类对象的类型,例如 Type[BaseClass] | 
| Self | 指代自身(Python 3.11+) | 
| 例如: |  | 
 NewType
创建“伪新类型”,用于静态类型区分
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | from typing import NewType
 UserId = NewType('UserId', int)
 
 def get_user_name(user_id: UserId) -> str:
 return f"User#{user_id}"
 
 get_user_name(UserId(123))
 
 
 | 
 Type
Type[T] 接收一个类对象(而不是实例)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 
 | from typing import Type
 class Animal:
 def speak(self) -> str:
 return "..."
 
 class Dog(Animal):
 def speak(self) -> str:
 return "Woof!"
 
 def make_animal(animal_cls: Type[Animal]) -> Animal:
 return animal_cls()
 
 a = make_animal(Dog)
 print(a.speak())
 
 | 
- Type[Animal]表示“Animal 的子类”,不是实例。
 Self(Python 3.11+)
用于方法返回当前类类型
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 
 | from typing import Self
 class Builder:
 def set_name(self, name: str) -> Self:
 self.name = name
 return self
 
 def set_age(self, age: int) -> Self:
 self.age = age
 return self
 
 b = Builder().set_name("Alice").set_age(30)
 
 | 
- Self 解决了链式调用返回类型难以表达的问题。
- 自动适配子类返回自身,无需硬编码类名。