Python 编程 - 类型注解
Python 3 类型注解完全指南
类型注解(Type Hints)是 Python 3.5 引入(通过 PEP 484)的一项功能,允许你在代码中显式声明变量、函数参数和返回值的预期类型。它不会影响运行时行为,但能显著提升代码的可读性、可维护性,并支持静态类型检查(如 mypy)和 IDE 智能提示。
1. 基本语法
函数注解
def greet(name: str) -> str:
return f"Hello, {name}"
name: str表示参数name期望为字符串。-> str表示函数返回字符串。
变量注解(Python 3.6+)
age: int = 25
name: str # 可以不赋初值,但需在后续赋值
类属性注解
class Person:
name: str
age: int
def __init__(self, name: str, age: int) -> None:
self.name = name
self.age = age
2. 内置类型与 typing 模块
简单内置类型
int, float, bool, str, bytes, None 等直接可用。
容器类型(Python 3.9+ 可直接使用内置泛型)
# Python 3.9 之前需要 typing.List, typing.Dict
def process(items: list[int]) -> dict[str, int]:
return {item: len(item) for item in items}
list[int]表示整数列表。dict[str, int]表示键为字符串、值为整数的字典。set[int],tuple[int, str]等类似。
typing 模块中的常用类型
| 类型 | 说明 |
|---|---|
Optional[T] |
等价于 T | None,表示可能为 None |
Union[T1, T2] |
多种类型之一(Python 3.10+ 可用 T1 | T2) |
Any |
任意类型,关闭类型检查 |
Literal["a", "b"] |
仅允许指定的字面值 |
Sequence[T] |
只读序列(如列表、元组) |
Iterable[T] |
可迭代对象 |
Callable[[Arg1, Arg2], Return] |
函数类型 |
Type[T] |
类的类型 |
3. 高级类型特性
联合类型(Union)
from typing import Union
def parse(value: Union[int, str]) -> float:
return float(value)
# Python 3.10+ 更简洁的写法
def parse(value: int | str) -> float:
return float(value)
可选类型(Optional)
from typing import Optional
def find_user(id: int) -> Optional[dict]:
# 可能返回 None
return None if id < 0 else {"id": id}
# 等价于 def find_user(id: int) -> dict | None:
类型别名
UserId = int
UserDict = dict[str, Union[int, str]]
泛型(类型变量)
from typing import TypeVar, Generic
T = TypeVar('T') # 声明类型变量
class Box(Generic[T]):
def __init__(self, content: T) -> None:
self.content = content
def get(self) -> T:
return self.content
box = Box[int](123) # 指定具体类型
受约束的类型变量
T = TypeVar('T', int, float) # 只能是 int 或 float
4. 特殊类型构造
TypedDict(指定字典结构)
from typing import TypedDict
class PersonDict(TypedDict):
name: str
age: int
email: str | None # Python 3.10+
def get_person() -> PersonDict:
return {"name": "Alice", "age": 30, "email": None}
Protocol(结构化子类型,类似接口)
from typing import Protocol
class Drawable(Protocol):
def draw(self) -> None: ...
def render(obj: Drawable) -> None:
obj.draw()
Final(常量,禁止重新赋值)
from typing import Final
MAX_SIZE: Final[int] = 100
# MAX_SIZE = 200 # 类型检查器会报错
TypeGuard(类型守卫)
from typing import TypeGuard
def is_str_list(val: list[object]) -> TypeGuard[list[str]]:
return all(isinstance(x, str) for x in val)
5. 类型注解在类中的应用
self 与 cls 不需要注解(但可标注)
@property 返回值
class Circle:
def __init__(self, radius: float) -> None:
self._radius = radius
@property
def area(self) -> float:
return 3.14 * self._radius ** 2
类方法与静态方法
class Math:
@classmethod
def from_string(cls, s: str) -> "Math": # 可使用字符串引用自身
...
@staticmethod
def add(a: int, b: int) -> int:
return a + b
6. 类型检查工具
- mypy:最流行的静态类型检查器。
pip install mypy mypy your_script.py - Pyright(VSCode 使用)和 pytype(Google)也是常用工具。
- IDE(PyCharm、VSCode)内置支持类型提示。
配置 pyproject.toml(或 mypy.ini)
[tool.mypy]
python_version = "3.10"
strict = true
ignore_missing_imports = true
7. 运行时行为
类型注解在运行时不会被强制检查,你可以通过 __annotations__ 访问它们:
def foo(x: int) -> str:
return str(x)
print(foo.__annotations__) # {'x': <class 'int'>, 'return': <class 'str'>}
如果你希望在运行时进行类型检查,可以使用第三方库如 typeguard 或 pydantic。
延迟注解求值(PEP 563, Python 3.7+)
默认情况下,注解中的类型名称会在定义时立即求值,可能导致 NameError(例如引用尚未定义的类)。可通过 from __future__ import annotations 将注解存储为字符串,延迟求值:
from __future__ import annotations
class Node:
def connect(self, other: Node) -> None: ... # 不再报错
8. 最佳实践与常见陷阱
- 不要过度注解:简单函数可省略,但复杂逻辑建议完整标注。
- 使用
Any要谨慎:它会关闭检查,尽量用object或Union。 - 避免循环引用:使用字符串字面量或
from __future__ import annotations。 - 使用类型别名提高可读性:
UserId = int比重复int更清晰。 - 为新项目启用严格模式:
mypy --strict可捕获更多问题。 - 兼容旧版本:如果需要支持 Python 3.8,使用
typing中的类型,而不是内置泛型(因为内置泛型是 3.9+)。
9. 新版本特性概览
- Python 3.8:
TypedDict、Literal、Final进入标准库。 - Python 3.9:内置泛型(
list[int])取代typing.List。 - Python 3.10:联合类型
|(int | str)和TypeGuard。 - Python 3.11:
Self类型(PEP 673),Never类型(PEP 684)。 - Python 3.12:更安全的类型变量语法(PEP 695)。
10. 示例汇总
from __future__ import annotations
from typing import Protocol, TypeVar, Generic, Literal, Optional
T = TypeVar('T')
class Stack(Generic[T]):
def __init__(self) -> None:
self._items: list[T] = []
def push(self, item: T) -> None:
self._items.append(item)
def pop(self) -> Optional[T]:
return self._items.pop() if self._items else None
class Comparable(Protocol):
def __lt__(self, other: object) -> bool: ...
def max_of(a: Comparable, b: Comparable) -> Comparable:
return a if a > b else b
# 使用
s = Stack[int]()
s.push(10)
s.push(20)
print(s.pop()) # 20
# 联合类型
def reply(status: Literal['ok', 'error']) -> str:
return f"Status: {status}"
结语
类型注解是 Python 向静态类型靠近的重要一步,它并非强制,但能极大地提升大型项目的代码质量和协作效率。结合 mypy 等工具,可以在开发阶段捕获大量类型错误,减少调试时间。

浙公网安备 33010602011771号