文章目录

Python 类型注解:typing 模块的详细使用

发布于 2026-04-10 11:18:29 · 浏览 6 次 · 评论 0 条

Python 类型注解:typing 模块的详细使用

理解 Python 类型注解是Python 3.5引入的功能,允许开发者在代码中显式声明变量、函数参数和返回值的预期数据类型。

安装 Python 3.9及以上版本已内置typing模块,无需额外安装。


为什么需要类型注解

提高 代码可读性:类型注解让代码更容易理解,特别是对于大型项目或团队协作。

增强 IDE功能:支持现代IDE如PyCharm、VSCode等提供更好的代码补全、静态分析和错误检查。

辅助 静态类型检查:配合mypy等工具可以在不运行代码的情况下发现类型错误。

实现 文档自包含:类型注解作为文档的一部分,减少单独编写文档的需要。


typing 模块基础类型

基本类型注解

声明 变量类型:

name: str = "Alice"
age: int = 30
height: float = 5.6
is_student: bool = True

声明 函数参数和返回值类型:

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

使用 类型别名提高可读性:

UserId = int
Username = str

def get_user_name(user_id: UserId) -> Username:
    # 函数实现
    pass

常用类型

查看 typing模块提供的常用类型:

类型 描述 示例
List 列表类型 List[int], List[str]
Tuple 元组类型 Tuple[int, str, float]
Dict 字典类型 Dict[str, int]
Set 集合类型 Set[int]
Optional 可选类型 Optional[int]等同于Union[int, None]
Union 联合类型 Union[int, str]
Any 任意类型 Any
Callable 可调用类型 Callable[[int, int], int]

容器类型注解

列表(List)

声明 单一类型列表:

from typing import List

numbers: List[int] = [1, 2, 3, 4, 5]
names: List[str] = ["Alice", "Bob", "Charlie"]

声明 嵌套列表:

matrix: List[List[int]] = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

元组(Tuple)

声明 固定长度和类型的元组:

from typing import Tuple

point: Tuple[int, int] = (3, 4)
person: Tuple[str, int, float] = ("Alice", 30, 5.6)

声明 不同长度元组:

# 可变长度元组
mixed: Tuple[str, ...] = ("a", "b", "c", "d", "e")

字典(Dict)

声明 键值对类型:

from typing import Dict

student_scores: Dict[str, int] = {
    "Alice": 90,
    "Bob": 85,
    "Charlie": 92
}

# 嵌套字典
nested_dict: Dict[str, Dict[str, int]] = {
    "class1": {"Alice": 90, "Bob": 85},
    "class2": {"Charlie": 92, "David": 88}
}

集合(Set)

声明 集合类型:

from typing import Set

unique_numbers: Set[int] = {1, 2, 3, 4, 5}
unique_words: Set[str] = {"apple", "banana", "cherry"}

高级类型

可选类型(Optional)和联合类型(Union)

使用 Optional 表示可能为None的值:

from typing import Optional

def find_user(user_id: int) -> Optional[dict]:
    # 查找用户,如果不存在返回None
    pass

使用 Union 表示多种可能的类型:

from typing import Union

def process_data(data: Union[int, str]) -> str:
    if isinstance(data, int):
        return f"Number: {data}"
    else:
        return f"String: {data}"

注意 在Python 3.10及以上,可以使用 | 操作符替代 Union

# Python 3.10+
def process_data(data: int | str) -> str:
    # 函数实现
    pass

可调用类型(Callable)

声明 函数作为参数或返回值:

from typing import Callable

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

def apply_operation(x: int, y: int, operation: Callable[[int, int], int]) -> int:
    return operation(x, y)

result = apply_operation(3, 4, add)  # 结果为7

生成器类型(Iterator, Generator)

声明 迭代器和生成器类型:

from typing import Iterator, Generator

def count_up_to(n: int) -> Iterator[int]:
    i = 1
    while i <= n:
        yield i
        i += 1

def infinite_counter() -> Generator[int, None, None]:
    i = 0
    while True:
        yield i
        i += 1

类型变量(TypeVar)

声明 泛型函数中的类型变量:

from typing import TypeVar, List

T = TypeVar('T')

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

# 使用示例
num = first_element([1, 2, 3])  # num类型为int
name = first_element(["Alice", "Bob"])  # name类型为str

约束类型变量

声明 有约束的类型变量:

from typing import TypeVar, Sequence

# T必须是Sequence的子类型
T = TypeVar('T', bound=Sequence[int])

def get_length(seq: T) -> int:
    return len(seq)

# 使用示例
list_len = get_length([1, 2, 3])  # 有效
tuple_len = get_length((1, 2, 3))  # 有效
str_len = get_length("hello")  # 有效,因为str是Sequence
dict_len = get_length({"a": 1})  # 无效,因为dict不是Sequence[int]

类型检查工具

使用 mypy进行静态类型检查:

# 安装mypy
pip install mypy

# 检查Python文件
mypy script.py

# 检查整个项目
mypy my_project/

配置 mypy配置文件(mypy.ini):

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

实际应用示例

数据模型类

创建 使用类型注解的数据模型:

from dataclasses import dataclass
from typing import List, Optional

@dataclass
class User:
    id: int
    name: str
    email: str
    age: Optional[int] = None
    friends: List[int] = None

    def __post_init__(self):
        if self.friends is None:
            self.friends = []

# 使用示例
user = User(id=1, name="Alice", email="alice@example.com")

API客户端

实现 带类型注解的API客户端:

from typing import Dict, Any, Optional
import requests

class APIClient:
    def __init__(self, base_url: str):
        self.base_url = base_url

    def get(self, endpoint: str, params: Optional[Dict[str, Any]] = None) -> Dict[str, Any]:
        response = requests.get(f"{self.base_url}{endpoint}", params=params)
        response.raise_for_status()
        return response.json()

    def post(self, endpoint: str, data: Dict[str, Any]) -> Dict[str, Any]:
        response = requests.post(f"{self.base_url}{endpoint}", json=data)
        response.raise_for_status()
        return response.json()

# 使用示例
client = APIClient("https://api.example.com")
user_data = client.get("/users/1")

数据处理管道

构建 使用类型注解的数据处理管道:

from typing import List, Callable, Any

def process_pipeline(data: List[Any], *processors: Callable[[List[Any]], List[Any]]) -> List[Any]:
    result = data
    for processor in processors:
        result = processor(result)
    return result

# 定义处理器函数
def filter_positive(numbers: List[int]) -> List[int]:
    return [n for n in numbers if n > 0]

def double_numbers(numbers: List[int]) -> List[int]:
    return [n * 2 for n in numbers]

# 使用示例
data = [-1, 2, -3, 4, 0, 5]
result = process_pipeline(data, filter_positive, double_numbers)
# 结果: [4, 8, 10]

性能考量

注意 类型注解本身不会影响运行时性能,因为Python是动态类型语言。

使用 from __future__ import annotations 在Python 3.7及以下版本中启用后向兼容的类型注解:

from __future__ import annotations

def func(a: int) -> str:
    return str(a)

考虑 在性能关键代码中,可以使用类型注解结合@typing.runtime_checkable装饰器实现运行时类型检查:

from typing import Protocol, runtime_checkable

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

def draw_object(obj: Drawable) -> None:
    obj.draw()

常见错误和最佳实践

避免 过度使用Any类型,这会失去类型检查的好处。

优先 使用具体类型而非Any

# 不推荐
def process(data: Any) -> Any:
    return str(data)

# 推荐
def process(data: Union[int, str]) -> str:
    return str(data)

使用 类型别名提高代码可读性:

# 不推荐
def get_user(id: int) -> Dict[str, Union[int, str, float]]: ...

# 推荐
UserId = int
UserInfo = Dict[str, Union[int, str, float]]

def get_user(id: UserId) -> UserInfo: ...

利用 类型注解作为文档的一部分,但不要仅依赖类型注解提供完整文档。

考虑 使用第三方库如pydanticdataclasses-json在需要序列化/反序列化时提供更高级的类型支持。

评论 (0)

暂无评论,快来抢沙发吧!

扫一扫,手机查看

扫描上方二维码,在手机上查看本文