类型注解(Type Hint)
基本概念
类型注解是一种 静态类型提示机制,用于在代码中标注变量、函数参数、返回值等的预期类型。
它不会改变 Python 的运行逻辑,只是为静态分析工具(如 mypy、pyright、pylance)提供类型信息。
📘 举例:
1 2
| def add(x: int, y: int) -> int: return x + y
|
运行时效果完全一样,但编辑器 / 检查工具能检测类型错误:
语法结构
| 用途 |
语法 |
示例 |
| 变量注解 |
变量名: 类型 |
count: int = 0 |
| 函数参数 |
def func(x: 类型): |
def greet(name: str): |
| 返回值 |
-> 类型 |
def f() -> float: |
| 类属性 |
在类体内注解 |
name: str |
| 类型别名 |
类型名 = 类型 |
Vector = list[float] |
常用类型注解
| 类型 |
示例 |
说明 |
| 基本类型 |
int, float, bool, str |
基础数据类型 |
| 容器类型 |
list[int], dict[str, int], tuple[int, ...] |
使用 [] 指定元素类型 |
| 可选类型 |
Optional[int] 或 int | None |
值可以为 None |
| 联合类型 |
Union[int, str] 或 int | str |
多种可能类型 |
| 任意类型 |
Any |
跳过类型检查 |
| 无返回值 |
-> None |
表示函数无返回 |
| 可调用类型 |
Callable[[int, str], bool] |
函数类型 |
📘 示例:
1 2 3 4 5 6 7 8 9 10 11
| from typing import Optional, Union, Any, Callable
def process(value: Union[int, str, None]) -> Any: if isinstance(value, int): return value * 2 elif isinstance(value, str): return value.upper() return None
def apply(func: Callable[[int], int], x: int) -> int: return func(x)
|
运行机制
类型注解只存在于运行时的函数对象中:
1 2 3 4 5
| def greet(name: str) -> str: return f"Hello {name}"
print(greet.__annotations__)
|
Python 本身 不会检查类型错误,但可以使用类型检查器:
输出示例:
1
| error: Argument 1 to "add" has incompatible type "str"; expected "int"
|
泛型(Generic)
泛型(Generic)是 可参数化的类型,即:让容器或类可以“带上类型信息”。
比如:
1 2 3 4 5 6 7 8 9 10 11 12 13
| from typing import Generic, TypeVar, List
T = TypeVar('T')
class Stack(Generic[T]): def __init__(self): self.items: List[T] = []
def push(self, item: T) -> None: self.items.append(item)
def pop(self) -> T: return self.items.pop()
|
使用:
1 2 3 4 5 6 7
| s1 = Stack[int]() s1.push(123) print(s1.pop())
s2 = Stack[str]() s2.push("abc") print(s2.pop())
|
💡 编译期会检测类型一致性。
类型变量(TypeVar)
TypeVar 是定义泛型的核心工具。
1 2 3
| from typing import TypeVar
T = TypeVar('T')
|
表示 “一个可变的类型参数”。
📘 用法举例:
1 2 3 4
| T = TypeVar('T')
def first(items: list[T]) -> T: return items[0]
|
- 若传入
list[int] → 推断 T=int
- 若传入
list[str] → 推断 T=str
✅ 类型安全:
1 2
| first([1, 2, 3]) first(["a", "b"])
|
限制类型变量
使用 bound
让 T 必须是某个类型或其子类:
1 2 3 4 5 6 7 8 9
| from typing import TypeVar
T = TypeVar('T', bound=str)
def shout(word: T) -> T: return word.upper()
shout("hello") shout(123)
|
使用 constraints
限制为多个特定类型之一:
1 2 3 4 5 6 7 8
| T = TypeVar('T', int, float)
def double(x: T) -> T: return x * 2
double(3) double(2.5) double("a")
|
内建泛型类型
在 Python 3.9 之后,可以直接使用内建泛型而无需从 typing 导入:
| 旧写法(<=3.8) |
新写法(>=3.9) |
List[int] |
list[int] |
Dict[str, int] |
dict[str, int] |
Tuple[int, ...] |
tuple[int, ...] |
Optional[int] |
int | None |
Union[int, str] |
int | str |
高级泛型应用
协变与逆变
TypeVar 可以指定是否协变或逆变(通常用于类型安全的泛型容器):
1 2 3
| from typing import TypeVar
T_co = TypeVar('T_co', covariant=True)
|
- 协变(covariant):子类可代替父类(如
List[Dog] 是 List[Animal] 的子类型)
- 逆变(contravariant):父类可代替子类(常用于函数参数)
这种机制在复杂类型系统中确保“类型替换安全”。
泛型函数与类型推导
1 2 3 4 5 6
| from typing import TypeVar
T = TypeVar('T')
def identity(x: T) -> T: return x
|
identity(10) → T=int
identity("hi") → T=str
类型检查器自动推导,不需要显式指定。
多类型变量函数
1 2 3 4 5 6 7
| from typing import TypeVar
T = TypeVar('T') U = TypeVar('U')
def pair(a: T, b: U) -> tuple[T, U]: return (a, b)
|
✅ 结果类型自动推导为 tuple[int, str] 等。
高级类型工具
| 类型工具 |
含义 |
示例 |
Any |
任意类型(跳过检查) |
x: Any |
NoReturn |
永不返回(函数异常结束) |
def fail() -> NoReturn: |
Literal |
限定具体值 |
Literal["GET", "POST"] |
Annotated |
额外元数据 |
Annotated[int, "age"] |
Final |
不可重写 |
PI: Final = 3.14 |
ClassVar |
类变量(非实例变量) |
counter: ClassVar[int] |
Self |
类自身类型(Python 3.11+) |
def copy(self) -> Self: |
类型检查与验证
静态检查
mypy
pyright
pylance(VS Code 内置)
运行:
动态验证
可以结合 typing + pydantic、beartype、typeguard 来在运行时验证类型。
1 2 3 4 5 6 7
| from typeguard import typechecked
@typechecked def add(x: int, y: int) -> int: return x + y
add(1, "2")
|
实际应用
数据处理函数
1 2
| def average(values: list[float]) -> float: return sum(values) / len(values)
|
泛型容器
1 2 3 4 5 6 7 8 9
| from typing import Generic, TypeVar
T = TypeVar('T')
class Box(Generic[T]): def __init__(self, content: T): self.content = content
b = Box[str]("apple")
|
自定义协议
1 2 3 4 5 6 7
| from typing import Protocol
class Speakable(Protocol): def speak(self) -> str: ...
def make_speak(x: Speakable): print(x.speak())
|
总结表
| 概念 |
含义 |
示例 |
| 类型注解 |
给变量/函数加类型提示 |
x: int, def f(x: str) -> bool: |
| 类型变量 |
泛型类型参数 |
T = TypeVar('T') |
| 泛型类 |
类中使用类型变量 |
class Box(Generic[T]): ... |
| 联合类型 |
多种可能类型 |
int | str |
| 可选类型 |
允许 None |
Optional[int] |
| 约束类型 |
限定范围 |
TypeVar('T', int, float) |
| 绑定类型 |
必须是某类型子类 |
TypeVar('T', bound=BaseClass) |
| 类型检查器 |
静态分析工具 |
mypy, pyright |