Python 类型提示:编写更安全、更清晰的代码

Backend2026-09-13TryQuickToolBox

你可能遇到过这样的情况:一个 Python 函数根据输入返回不同的类型,或者一个变量在中间改变了类型。这些模糊性会导致本可以更早发现的运行时错误。Python 类型提示通过让你标注预期的类型来解决这个问题,使你的代码具有自文档性,并让静态分析工具在执行前捕获错误。

在本文中,我们将探讨如何有效地使用 Python 中的类型提示,从基本注解到高级模式,以及它们如何帮助编写更安全、更清晰的代码。

什么是 Python 类型提示?

类型提示(也称为类型注解)是 Python 3.5(PEP 484)引入的一种语法,允许你指定变量、函数参数和返回值的预期类型。它们不会在运行时强制执行,但会被 mypy、pyright 和 IDE 等静态类型检查器用来检测类型相关的错误。

例如:

def greet(name: str) -> str:
    return f"Hello, {name}"

这里,name: str 表示 name 应该是字符串,而 -> str 表示函数返回字符串。

为什么要使用类型提示?

基本类型注解

你可以注解变量、函数参数和返回类型。

变量

age: int = 30
name: str = "Alice"

函数

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

集合

对于列表、字典等,使用 typing 模块(或 Python 3.9+ 中的内置泛型):

from typing import List, Dict

def process(items: List[str]) -> Dict[str, int]:
    return {item: len(item) for item in items}

在 Python 3.9+ 中,你可以直接使用 list[str] 和 dict[str, int]。

高级类型提示

随着代码的增长,你会遇到更复杂的场景。以下是一些高级特性。

Optional 和 Union

Optional[T] 是 Union[T, None] 的简写,表示一个值可以是 T 类型或 None。

from typing import Optional

def find_user(user_id: int) -> Optional[str]:
    # 返回用户名,如果未找到则返回 None
    ...

在 Python 3.10+ 中,你可以使用 | 运算符:str | None。

Callable

用于将函数作为参数:

from typing import Callable

def apply_func(func: Callable[[int], int], value: int) -> int:
    return func(value)

泛型

使用类型变量创建可重用组件:

from typing import TypeVar, List

T = TypeVar('T')

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

TypedDict

用于具有固定键集和值类型的字典:

from typing import TypedDict

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

def greet(user: User) -> str:
    return f"Hello, {user['name']}"

使用静态类型检查器

类型提示只有在你检查它们时才有用。流行的工具包括 mypy、pyright 和 pyre。让我们看看如何使用 mypy。

  1. 安装 mypy:pip install mypy
  2. 在代码上运行它:mypy your_script.py
  3. 修复报告的错误。

例如,给定:

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

add("1", "2")

mypy 会报告:error: Argument 1 to "add" has incompatible type "str"; expected "int"。

你可以通过 mypy.ini 或 pyproject.toml 文件配置 mypy 以执行更严格的检查。

类型提示的最佳实践

常见陷阱及如何避免

实践中的类型提示:一个小例子

考虑一个处理数字列表并返回平均值的函数。没有类型提示,不清楚期望什么类型。

def average(numbers):
    return sum(numbers) / len(numbers)

使用类型提示:

from typing import List

def average(numbers: List[float]) -> float:
    return sum(numbers) / len(numbers)

现在,如果有人传递一个字符串列表,mypy 会标记它。

将类型提示集成到你的工作流程中

为了充分利用类型提示,将它们集成到你的开发过程中:

  1. 逐步向现有代码库添加类型提示。
  2. 配置你的 IDE 以显示类型错误。
  3. 在 CI 管道中添加类型检查步骤。
  4. 使用 pre-commit 钩子在提交前运行 mypy。

例如,一个简单的 GitHub Actions 工作流步骤:

- name: Type check
  run: mypy .

常见问题

类型提示会影响运行时性能吗?

不会,类型提示在运行时被忽略。它们存储在 __annotations__ 中,但不会影响执行速度。

我可以在较旧的 Python 版本中使用类型提示吗?

类型提示在 Python 3.5 中引入。对于较旧的版本,你可以使用基于注释的注解(例如 # type: int),但建议升级到受支持的 Python 版本。

类型提示中 List 和 list 有什么区别?

typing 中的 List 用于 Python 3.5-3.8。在 Python 3.9+ 中,你可以直接使用内置的 list。两者在类型检查方面是等效的。

准备好提高你的代码质量了吗?今天就从为一个函数添加类型提示开始,并运行 mypy 来查看好处。如需更多开发者工具,请查看我们的 JSON Formatter,轻松美化和验证你的 JSON 数据。