函数签名注解

def greet(name: str, age: int = 18) -> str:
    return f"{name} 今年 {age}"

参数后加 : 类型,返回值用 -> 类型Python 不会强制检查——它只是元数据,给 IDE / mypy / 同事看。

容器类型(Python 3.9+ 简写)

def process(nums: list[int]) -> dict[str, int]:
    return {"count": len(nums)}

# Python 3.8 及以下要这样:
from typing import List, Dict
def process(nums: List[int]) -> Dict[str, int]: ...

新代码用小写内置——更简洁。

可选与联合:Optional / Union

def find(uid: int) -> str | None:           # 3.10+ 写法
    if uid in db:
        return db[uid]
    return None

# 等价的老写法
from typing import Optional
def find(uid: int) -> Optional[str]: ...

多种类型可能:

def to_int(x: int | str) -> int:            # 3.10+
    return int(x)

# 等价老写法
from typing import Union
def to_int(x: Union[int, str]) -> int: ...

Any:任意类型(逃避检查时用)

from typing import Any

def cache_get(key: str) -> Any:
    return CACHE[key]

Any = "我不想标,类型检查器请放过"。慎用——失去类型注解的好处。

Literal:值的"枚举"

from typing import Literal

def open_mode(mode: Literal["r", "w", "a"]) -> None:
    ...

open_mode("r")        # OK
open_mode("rw")       # mypy 报错

Callable:函数类型

from typing import Callable

def apply(fn: Callable[[int, int], int], a: int, b: int) -> int:
    return fn(a, b)

apply(lambda x, y: x + y, 3, 4)

Callable[[参数类型...], 返回类型]

Generic / TypeVar:泛型

写一个保留类型信息的"通用容器":

from typing import TypeVar

T = TypeVar("T")

def first(xs: list[T]) -> T:
    return xs[0]

x = first([1, 2, 3])         # x 推断成 int
s = first(["a", "b", "c"])   # s 推断成 str

类的泛型:

from typing import Generic

class Box(Generic[T]):
    def __init__(self, value: T):
        self.value = value

    def get(self) -> T:
        return self.value


b: Box[int] = Box(42)
v: int = b.get()

TypedDict:dict 的形状

from typing import TypedDict

class User(TypedDict):
    name: str
    age: int

def show(u: User) -> None:
    print(u["name"])

show({"name": "WadeLy", "age": 30})        # OK
show({"name": "X"})                         # mypy 报错:缺 age

标准复杂类型:怎么注解

from typing import Iterable, Iterator, Sequence, Mapping

def avg(nums: Iterable[float]) -> float: ...    # 接收任意可迭代
def lines() -> Iterator[str]: ...                # 返回迭代器
def head(seq: Sequence[int]) -> int: ...         # 列表 / 元组都行
def show(d: Mapping[str, int]) -> None: ...      # 只读字典

注解只是写给人看的——除非你跑 mypy

pip install mypy
mypy myfile.py

下一篇专门讲 mypy 怎么用。