Python 类型注解

Annotations for readability and tooling, Optional/Union syntax, generics, and dataclasses.

Intermediate
Key PointsHints are not enforced at runtime; they power IDE completion, mypy/pyright checks and FastAPI/Pydantic validation.

Basic Annotations

Python
def greet(name: str, times: int = 1) -> str:
    return f"Hello, {name}! " * times


def log(msg: str) -> None:
    print(msg)


# 变量注解
count: int = 0
names: list[str] = []
mapping: dict[str, int] = {}

Optional and Union

X | None (3.10+) is the modern way to say Optional[X]. Union[A, B] becomes A | B. Runtime does not care — but the checker will catch the None branch you forgot.

Python
def find_user(uid: int) -> dict | None:
    return None


def parse(value: str | int) -> int:
    return int(value)


# 3.9 及更早:from typing import Optional, Union

Generics and Callables

Python
from collections.abc import Callable, Iterable, Iterator, Sequence


def first(items: Sequence[int]) -> int:
    return items[0]


def apply_all(func: Callable[[int], int], data: Iterable[int]) -> Iterator[int]:
    for x in data:
        yield func(x)


def index_by(rows: list[dict], key: str) -> dict[str, dict]:
    return {r[key]: r for r in rows}

Protocol: Structural Typing

Protocol describes behaviour instead of a class hierarchy — any object with matching methods satisfies it. This is duck typing with static checking.

Python
from typing import Protocol


class Readable(Protocol):
    def read(self) -> bytes: ...


def load(src: Readable) -> bytes:
    return src.read()


# 任何有 read() 的对象都可以传进来:文件、socket、StringIO

dataclass

@dataclass generates __init__, __repr__ and __eq__ from the field declarations. frozen=True adds immutability and hashability.

Python
from dataclasses import dataclass, field


@dataclass
class Point:
    x: int
    y: int
    tags: list[str] = field(default_factory=list)   # 可变默认值必须用 factory


@dataclass(frozen=True)
class Config:
    host: str = "127.0.0.1"
    port: int = 8000


p = Point(1, 2)
print(p)                        # Point(x=1, y=2, tags=[])
print(p == Point(1, 2, []))     # True
print(hash(Config()))           # 可哈希
Never use a mutable default (tags: list = []) in a dataclass — Python raises ValueError and tells you to use field(default_factory=...).

Checking Types

Bash
pip install mypy
mypy app/ --strict

# 或更快的 pyright / basedpyright

Friends & Partners