惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

S
SegmentFault 最新的问题
Spread Privacy
Spread Privacy
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
Blog — PlanetScale
Blog — PlanetScale
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Apple Machine Learning Research
Apple Machine Learning Research
SecWiki News
SecWiki News
腾讯CDC
P
Privacy International News Feed
Webroot Blog
Webroot Blog
J
Java Code Geeks
爱范儿
爱范儿
A
About on SuperTechFans
S
Secure Thoughts
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
D
DataBreaches.Net
Cloudbric
Cloudbric
Security Archives - TechRepublic
Security Archives - TechRepublic
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
C
Cyber Attacks, Cyber Crime and Cyber Security
P
Proofpoint News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Security Latest
Security Latest
Forbes - Security
Forbes - Security
小众软件
小众软件
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Cybersecurity and Infrastructure Security Agency CISA
T
Threatpost
量子位
MongoDB | Blog
MongoDB | Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
月光博客
月光博客
W
WeLiveSecurity
P
Privacy & Cybersecurity Law Blog
Vercel News
Vercel News
Google Online Security Blog
Google Online Security Blog
云风的 BLOG
云风的 BLOG
GbyAI
GbyAI
S
Security @ Cisco Blogs
T
The Exploit Database - CXSecurity.com
Help Net Security
Help Net Security
V
Visual Studio Blog
C
CXSECURITY Database RSS Feed - CXSecurity.com
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 聂微东
P
Proofpoint News Feed
C
CERT Recently Published Vulnerability Notes
Attack and Defense Labs
Attack and Defense Labs

🕵️‍♂️匿名运维栈

Uv 完全指南 - 🕵️‍♂️匿名运维栈 2025:大语言模型(LLM)之年 - 🕵️‍♂️匿名运维栈 AI 代码指南 [转载] - 🕵️‍♂️匿名运维栈 Lsky Pro + Typora 图床搭建 Docker构建多架构镜像 - 🕵️‍♂️匿名运维栈 DNS 域名解析工具 - 🕵️‍♂️匿名运维栈 Ubuntu DNS解析失败排查记录:EasyConnect VPN劫持问题完全解析 - 🕵️‍♂️匿名运维栈 高效休息法:学习效率提升的科学指南 - 🕵️‍♂️匿名运维栈 Claude Code 子代理(Subagents)完全学习指南 - 🕵️‍♂️匿名运维栈
Python typing类型注解完全指南 - 🕵️‍♂️匿名运维栈
nwnusun · 2026-02-12 · via 🕵️‍♂️匿名运维栈

共计 11642 个字符,预计需要花费 30 分钟才能阅读完成。

本文全面讲解 Python 的类型注解系统,包括基础用法、高级特性、版本演进和最佳实践。


  1. 类型注解简介
  2. 基础类型注解
  3. 容器类型注解
  4. 函数类型注解
  5. 高级类型
  6. 泛型
  7. 协议和结构化子类型
  8. 类型别名
  9. 版本演进
  10. 类型检查工具
  11. 最佳实践

类型注解(Type Hints)是 Python 3.5 引入的特性,允许在代码中标注变量、函数参数和返回值的类型。

重要: 类型注解是可选的,不影响运行时行为,主要用于:

  • 代码文档化
  • IDE 智能提示
  • 静态类型检查(mypy 等工具)
  • 提高代码可维护性
# 没有类型注解
def greet(name):
    return f"Hello, {name}"

# 有类型注解
def greet(name: str) -> str:
    return f"Hello, {name}"
# 优势 1:IDE 智能提示
def calculate_area(radius: float) -> float:
    return 3.14 * radius ** 2

# IDE 会提示 radius 应该是 float 类型
result = calculate_area(5.0)  # ✓
# result = calculate_area("5")  # IDE 会警告

# 优势 2:提前发现错误
def process_items(items: list[str]) -> int:
    return len(items)

# 优势 3:代码文档化
def fetch_user(user_id: int) -> dict[str, str]:
    """
    通过类型注解就能知道:- user_id 是整数
    - 返回字典,键和值都是字符串
    """return {"name":"Alice","email":"[email protected]"}

# 基本类型
age: int = 25
price: float = 19.99
name: str = "Alice"
is_active: bool = True
data: bytes = b"hello"

# None 类型
result: None = None

# Any 类型(任意类型)from typing import Any
value: Any = "can be anything"
value = 123  # 也可以 
# Python 3.6+:变量注解
count: int
count = 10

# 可以不立即赋值
name: str
# ... 稍后赋值
name = "Bob"

# 类属性注解
class User:
    name: str
    age: int

    def __init__(self, name: str, age: int):
        self.name = name
        self.age = age

from typing import List, Dict, Set, Tuple

# Python 3.9 之前
names: List[str] = ["Alice", "Bob"]
scores: Dict[str, int] = {"Alice": 95, "Bob": 87}
tags: Set[int] = {1, 2, 3}
point: Tuple[int, int] = (10, 20)

# Python 3.9+:使用内置类型(推荐)names: list[str] = ["Alice", "Bob"]
scores: dict[str, int] = {"Alice": 95, "Bob": 87}
tags: set[int] = {1, 2, 3}
point: tuple[int, int] = (10, 20)
# 嵌套列表
matrix: list[list[int]] = [[1, 2], [3, 4]]

# 复杂字典
user_data: dict[str, list[int]] = {"Alice": [95, 87, 92],
    "Bob": [78, 85, 90]
}

# 字典的字典
config: dict[str, dict[str, str]] = {"database": {"host": "localhost", "port": "5432"},
    "cache": {"host": "localhost", "port": "6379"}
}
# 固定长度元组
point: tuple[int, int] = (10, 20)

# 可变长度元组
numbers: tuple[int, ...] = (1, 2, 3, 4, 5)

# 空元组
empty: tuple[()] = ()

# 参数和返回值注解
def add(a: int, b: int) -> int:
    return a + b

# 无返回值
def log_message(message: str) -> None:
    print(message)

# 多个参数
def create_user(name: str, age: int, email: str) -> dict[str, str | int]:
    return {"name": name, "age": age, "email": email}
def greet(name: str, greeting: str = "Hello") -> str:
    return f"{greeting}, {name}"

# 可选参数
from typing import Optional

def find_user(user_id: int) -> Optional[dict]:
    # 可能返回 dict 或 None
    if user_id > 0:
        return {"id": user_id, "name": "Alice"}
    return None
# *args 和 **kwargs
def sum_all(*args: int) -> int:
    return sum(args)

def print_info(**kwargs: str) -> None:
    for key, value in kwargs.items():
        print(f"{key}: {value}")

# 混合使用
def process(
    required: str,
    *args: int,
    optional: str = "default",
    **kwargs: str
) -> None:
    pass
from typing import Callable

# 函数作为参数
def apply_operation(x: int, y: int, op: Callable[[int, int], int]) -> int:
    return op(x, y)

def add(a: int, b: int) -> int:
    return a + b

result = apply_operation(5, 3, add)

# 无参数函数
def run_callback(callback: Callable[[], None]) -> None:
    callback()

# 任意参数函数
from typing import Any
def run_function(func: Callable[..., Any]) -> Any:
    return func()

from typing import Union

# Union:多种类型之一
def process_id(id: Union[int, str]) -> str:
    return str(id)

process_id(123)      # ✓
process_id("abc")    # ✓

# Python 3.10+:使用 | 运算符(推荐)def process_id(id: int | str) -> str:
    return str(id)
from typing import Optional

# Optional[X] 等价于 Union[X, None]
def find_user(user_id: int) -> Optional[dict]:
    if user_id > 0:
        return {"id": user_id}
    return None

# Python 3.10+
def find_user(user_id: int) -> dict | None:
    if user_id > 0:
        return {"id": user_id}
    return None
from typing import Literal

# 限制为特定值
def set_mode(mode: Literal["read", "write", "append"]) -> None:
    print(f"Mode: {mode}")

set_mode("read")    # ✓
# set_mode("delete")  # 类型检查错误

# 多个字面量
Status = Literal["pending", "approved", "rejected"]

def update_status(status: Status) -> None:
    pass
from typing import Final

# 常量(不应被修改)MAX_SIZE: Final = 100
API_KEY: Final[str] = "secret-key"

# MAX_SIZE = 200  # 类型检查器会警告

# 类中的 Final
class Config:
    MAX_RETRIES: Final = 3

    def __init__(self):
        self.timeout: Final = 30  # 实例常量 
from typing import TypedDict

# 定义字典结构
class User(TypedDict):
    name: str
    age: int
    email: str

user: User = {
    "name": "Alice",
    "age": 25,
    "email": "[email protected]"
}

# 可选字段
class UserOptional(TypedDict, total=False):
    name: str
    age: int
    email: str  # 可选

# Python 3.11+:Required 和 NotRequired
from typing import Required, NotRequired

class UserMixed(TypedDict):
    name: Required[str]      # 必需
    age: NotRequired[int]    # 可选 
from typing import NewType

# 创建新类型(用于区分相同基础类型)UserId = NewType('UserId', int)
ProductId = NewType('ProductId', int)

def get_user(user_id: UserId) -> dict:
    return {"id": user_id}

def get_product(product_id: ProductId) -> dict:
    return {"id": product_id}

user_id = UserId(123)
product_id = ProductId(456)

get_user(user_id)        # ✓
# get_user(product_id)   # 类型检查错误
# get_user(123)          # 类型检查错误 

from typing import TypeVar, List

# 定义类型变量
T = TypeVar('T')

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

# 自动推断类型
numbers = [1, 2, 3]
first_num = first(numbers)  # 推断为 int

names = ["Alice", "Bob"]
first_name = first(names)   # 推断为 str

新写法 (Python 3.12+)

# 1. 直接写 [T],意思就是:我要定义一个泛型 T
def first[T](items: list[T]) -> T:
    return items[0]
from typing import Generic, TypeVar

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()

# 使用泛型类
int_stack: Stack[int] = Stack()
int_stack.push(1)
int_stack.push(2)

str_stack: Stack[str] = Stack()
str_stack.push("hello")

新写法

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

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

# 使用
box1 = Box(123)      # T 推断为 int
box2 = Box("Hello")  # T 推断为 str
from typing import TypeVar

# 约束为特定类型
T = TypeVar('T', int, float)

def add(a: T, b: T) -> T:
    return a + b

add(1, 2)      # ✓ int
add(1.5, 2.5)  # ✓ float
# add("a", "b")  # 错误

# 约束为某个基类的子类
from typing import TypeVar

class Animal:
    pass

class Dog(Animal):
    pass

T = TypeVar('T', bound=Animal)

def process_animal(animal: T) -> T:
    return animal

process_animal(Dog())  # ✓
# process_animal("not an animal")  # 错误 

from typing import Protocol

# 定义协议
class Drawable(Protocol):
    def draw(self) -> None:
        ...

# 任何实现了 draw 方法的类都满足协议
class Circle:
    def draw(self) -> None:
        print("Drawing circle")

class Square:
    def draw(self) -> None:
        print("Drawing square")

def render(shape: Drawable) -> None:
    shape.draw()

render(Circle())  # ✓
render(Square())  # ✓
from typing import Protocol, runtime_checkable

@runtime_checkable
class Closeable(Protocol):
    def close(self) -> None:
        ...

class File:
    def close(self) -> None:
        print("Closing file")

f = File()
print(isinstance(f, Closeable))  # True

# 类型别名
Vector = list[float]

def scale(vector: Vector, factor: float) -> Vector:
    return [x * factor for x in vector]

# 复杂类型别名
JSON = dict[str, Any]
Headers = dict[str, str]
Callback = Callable[[int], None]
from typing import TypeAlias

# 显式声明类型别名
Vector: TypeAlias = list[float]
JSON: TypeAlias = dict[str, Any]

  • 引入 typing 模块
  • 基础类型注解
  • List, Dict, Set, Tuple 等
from typing import List, Dict

def process(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}
  • 变量注解语法
# 变量注解
name: str = "Alice"
count: int

class User:
    name: str
    age: int
  • 延迟注解评估(from __future__ import annotations
from __future__ import annotations

class Node:
    def __init__(self, value: int, next: Node | None = None):
        self.value = value
        self.next = next  # 可以引用自身 
  • Protocol 协议
  • Literal 类型
  • Final 类型
  • TypedDict
from typing import Protocol, Literal, Final, TypedDict

class Drawable(Protocol):
    def draw(self) -> None: ...

Mode = Literal["r", "w", "a"]
MAX_SIZE: Final = 100

class User(TypedDict):
    name: str
    age: int
  • 使用内置类型进行泛型注解(不需要 typing 模块)
# Python 3.9+:直接使用内置类型
def process(items: list[str]) -> dict[str, int]:
    return {item: len(item) for item in items}

# 不再需要
from typing import List, Dict
  • Union 类型使用 | 运算符
  • TypeAlias
  • ParamSpec
# Union 使用 |
def process(value: int | str) -> str:
    return str(value)

# TypeAlias
from typing import TypeAlias
Vector: TypeAlias = list[float]

# ParamSpec(高级)from typing import ParamSpec, Callable
P = ParamSpec('P')

def decorator(func: Callable[P, int]) -> Callable[P, int]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> int:
        return func(*args, **kwargs)
    return wrapper
  • Self 类型
  • TypeVarTuple
  • Required 和 NotRequired
from typing import Self

class Builder:
    def set_name(self, name: str) -> Self:
        self.name = name
        return self

# Required 和 NotRequired
from typing import TypedDict, Required, NotRequired

class User(TypedDict):
    name: Required[str]
    age: NotRequired[int]
  • 泛型语法改进
  • type 语句
# 新的泛型语法
def first[T](items: list[T]) -> T:
    return items[0]

class Stack[T]:
    def __init__(self):
        self._items: list[T] = []

# type 语句
type Vector = list[float]
type Matrix = list[Vector]

最流行的 Python 静态类型检查器。

# 安装
pip install mypy

# 检查文件
mypy script.py

# 检查目录
mypy src/

配置文件(mypy.ini):

[mypy]
python_version = 3.11
warn_return_any = True
warn_unused_configs = True
disallow_untyped_defs = True

微软开发的类型检查器,速度快。

# 安装
pip install pyright

# 检查
pyright

Facebook 开发的类型检查器。

# 安装
pip install pyre-check

# 初始化
pyre init

# 检查
pyre check

# 从关键函数开始
def calculate_total(items: list[dict]) -> float:
    return sum(item['price'] for item in items)

# 逐步添加更详细的类型
from typing import TypedDict

class Item(TypedDict):
    name: str
    price: float
    quantity: int

def calculate_total(items: list[Item]) -> float:
    return sum(item['price'] * item['quantity'] for item in items)
# 不好
def process(data: dict[str, list[tuple[int, str]]]) -> list[dict[str, int]]:
    pass

# 好
UserId = int
UserName = str
UserData = tuple[UserId, UserName]
UserMap = dict[str, list[UserData]]
Result = list[dict[str, int]]

def process(data: UserMap) -> Result:
    pass
from typing import Any

# 不好
def process(data: Any) -> Any:
    return data

# 好:尽可能具体
def process(data: dict[str, int]) -> list[int]:
    return list(data.values())

# 如果真的不确定,使用泛型
from typing import TypeVar
T = TypeVar('T')

def identity(value: T) -> T:
    return value
# 不够灵活
from abc import ABC, abstractmethod

class Drawable(ABC):
    @abstractmethod
    def draw(self) -> None:
        pass

# 更灵活:使用 Protocol
from typing import Protocol

class Drawable(Protocol):
    def draw(self) -> None:
        ...

# 任何有 draw 方法的类都自动满足
class Circle:
    def draw(self) -> None:
        print("Drawing circle")
# 不好
def create_user(name: str, age: int) -> dict:
    return {"name": name, "age": age}

# 好
from typing import TypedDict

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

def create_user(name: str, age: int) -> User:
    return {"name": name, "age": age}
# Python 3.7-3.8 兼容
from __future__ import annotations
from typing import Optional

def process(value: int | None) -> str:  # 使用 | 语法
    return str(value) if value else "None"

# 或者使用 typing_extensions
from typing_extensions import Literal

Mode = Literal["read", "write"]
def calculate_discount(
    price: float,
    discount_rate: float,
    min_price: float = 0.0
) -> float:
    """
    计算折扣后的价格。Args:
        price: 原价
        discount_rate: 折扣率(0- 1 之间)min_price: 最低价格

    Returns:
        折扣后的价格

    Raises:
        ValueError: 如果 discount_rate 不在 0 - 1 之间
    """
    if not 0 <= discount_rate <= 1:
        raise ValueError("折扣率必须在 0 - 1 之间")

    discounted = price * (1 - discount_rate)
    return max(discounted, min_price)
# 使用 mypy 的 reveal_type 查看推断的类型
def process(items: list[int]) -> None:
    reveal_type(items)  # mypy 会显示:list[int]
    first = items[0]
    reveal_type(first)  # mypy 会显示:int

from typing import TypeVar, Type

T = TypeVar('T')

def create_instance(cls: Type[T], *args, **kwargs) -> T:
    return cls(*args, **kwargs)

class User:
    def __init__(self, name: str):
        self.name = name

user = create_instance(User, "Alice")  # 类型推断为 User
from typing import Callable, TypeVar, ParamSpec

P = ParamSpec('P')
R = TypeVar('R')

def log_calls(func: Callable[P, R]) -> Callable[P, R]:
    def wrapper(*args: P.args, **kwargs: P.kwargs) -> R:
        print(f"Calling {func.__name__}")
        return func(*args, **kwargs)
    return wrapper

@log_calls
def add(a: int, b: int) -> int:
    return a + b
from typing import ContextManager
from contextlib import contextmanager

@contextmanager
def open_file(filename: str) -> ContextManager[str]:
    f = open(filename)
    try:
        yield f.read()
    finally:
        f.close()
from typing import Coroutine, Any

async def fetch_data(url: str) -> dict[str, Any]:
    # 模拟异步操作
    return {"data": "example"}

# 返回类型是 Coroutine
def get_fetcher() -> Coroutine[Any, Any, dict[str, Any]]:
    return fetch_data("http://example.com")

  1. 类型注解是可选的 :不影响运行时,主要用于文档和静态检查
  2. 渐进式采用 :从关键函数开始,逐步完善
  3. 版本差异 :Python 3.9+ 可以直接使用内置类型,3.10+ 支持 | 语法
  4. 工具支持 :使用 mypy、pyright 等工具进行类型检查
  5. 最佳实践 :使用类型别名、Protocol、TypedDict 提高代码质量
  • Python 3.9+:使用内置类型(list, dict 等)
  • Python 3.10+:使用 | 运算符替代 Union
  • Python 3.11+:使用 Self、Required/NotRequired
  • Python 3.12+:使用新的泛型语法
  1. 基础 :基本类型注解、函数注解
  2. 进阶 :容器类型、Optional、Union
  3. 高级 :泛型、Protocol、TypedDict
  4. 专家 :ParamSpec、Concatenate、高级泛型

结语

类型注解是 Python 现代化的重要特性,虽然是可选的,但能显著提高代码质量和可维护性。建议在新项目中积极使用,在旧项目中渐进式引入。随着 Python 版本的演进,类型系统越来越强大和易用,值得深入学习和实践。