导航菜单

  • 1.vector
  • 2.milvus
  • 3.pymilvus
  • 4.rag
  • 5.rag_measure
  • 7.search
  • ragflow
  • heapq
  • HNSW
  • cosine_similarity
  • math
  • typing
  • etcd
  • minio
  • collections
  • jieba
  • random
  • beautifulsoup4
  • chromadb
  • sentence_transformers
  • numpy
  • lxml
  • openpyxl
  • PyMuPDF
  • python-docx
  • requests
  • python-pptx
  • text_splitter
  • all-MiniLM-L6-v2
  • openai
  • llm
  • BPETokenizer
  • Flask
  • RAGAS
  • BagofWords
  • langchain
  • Pydantic
  • abc
  • faiss
  • MMR
  • scikit-learn
  • 1. typing 模块
  • 2. 导入 typing 模块
  • 3. 基本类型提示
    • 3.1. 简单类型
    • 3.2. 容器类型
  • 4. 高级类型提示
    • 4.1. Optional 类型
    • 4.2. Union 类型
    • 4.3. Any 类型
    • 4.4. Callable 类型
  • 5. 泛型和类型变量
    • 5.1. TypeVar
    • 5.2. 泛型类
  • 6. 更复杂的类型
    • 6.1. Literal 类型
    • 6.2. Final 类型
    • 6.3. NewType
  • 7. 实际应用示例
    • 7.1 示例 1:数据处理函数
    • 7.2 示例 2:回调系统
  • 8. Python 3.9+ 的新语法
  • 9. 总结

1. typing 模块 #

typing 模块是 Python 内置的类型提示工具,帮助我们显式标注函数与变量的类型,便于阅读、调试与静态检查。

2. 导入 typing 模块 #

开始使用前先掌握如何导入常用的类型别名或整个模块。

# 说明:从 typing 模块导入常见类型别名
from typing import List, Dict, Tuple, Set, Optional, Union, Any, Callable
# 说明:也可以整体导入 typing 模块
import typing

3. 基本类型提示 #

这一部分先介绍最常见的标注方式,涵盖标量类型与容器类型。

3.1. 简单类型 #

用于标注函数参数与返回值的基础类型:字符串、整数、浮点与布尔值。

# 说明:定义问候函数,参数与返回值均为字符串
def greet(name: str) -> str:
    return f"Hello, {name}"

# 说明:定义计算圆面积的函数,返回浮点结果
def calculate_area(radius: float) -> float:
    return 3.14159 * radius ** 2

# 说明:定义判断偶数的函数,返回布尔值
def is_even(number: int) -> bool:
    return number % 2 == 0

# 说明:脚本入口,演示上述函数的返回值类型
if __name__ == "__main__":
    result: str = greet("Alice")
    area: float = calculate_area(5.0)
    check: bool = is_even(10)
    print(result, area, check)

3.2. 容器类型 #

当函数需要处理列表、字典、元组或集合时,应同时标注元素类型以便阅读。

# 说明:导入容器类型别名
from typing import List, Dict, Tuple, Set

# 说明:定义函数,输入整数列表,返回缩放后的浮点列表
def process_numbers(numbers: List[int]) -> List[float]:
    return [x * 1.5 for x in numbers]

# 说明:定义函数,返回姓名到分数的映射
def get_student_grades() -> Dict[str, int]:
    return {"Alice": 95, "Bob": 87, "Charlie": 92}

# 说明:定义函数,返回经纬度坐标的元组
def get_coordinates() -> Tuple[float, float]:
    return (40.7128, -74.0060)

# 说明:定义函数,接收字符串列表并返回唯一元素集合
def get_unique_items(items: List[str]) -> Set[str]:
    return set(items)

# 说明:脚本入口,调用各容器函数
if __name__ == "__main__":
    numbers: List[int] = [1, 2, 3, 4, 5]
    grades: Dict[str, int] = get_student_grades()
    coordinates: Tuple[float, float] = get_coordinates()
    unique: Set[str] = get_unique_items(["a", "b", "a", "c"])
    print(process_numbers(numbers))
    print(grades)
    print(coordinates)
    print(unique)

4. 高级类型提示 #

实际业务中参数可能允许多种类型或可为空,需要更灵活的注解写法。

4.1. Optional 类型 #

当返回值可能为具体类型或 None 时,使用 Optional[T] 更易读。

# 说明:导入 Optional 用于表示“可能为 None”
from typing import Optional

# 说明:根据用户 ID 返回姓名,若不存在则返回 None
def find_user(user_id: int) -> Optional[str]:
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)

# 说明:Python 3.10+ 可用联合类型语法表示相同含义
def find_user_v2(user_id: int) -> str | None:
    users = {1: "Alice", 2: "Bob"}
    return users.get(user_id)

# 说明:脚本入口,演示如何安全地处理 Optional
if __name__ == "__main__":
    user: Optional[str] = find_user(1)
    if user is not None:
        print(f"Found user: {user}")
    else:
        print("User not found")

4.2. Union 类型 #

Union 表示“可以是多种类型之一”,Python 3.10+ 也能用 | 简写。

# 说明:导入 Union 来表示多种可能的输入类型
from typing import Union

# 说明:接受整数、浮点或字符串,统一转换为字符串
def process_value(value: Union[int, float, str]) -> str:
    return str(value)

# 说明:Python 3.10+ 可使用更直观的管道写法
def process_value_v2(value: int | float | str) -> str:
    return str(value)

# 说明:脚本入口,演示不同输入类型的结果
if __name__ == "__main__":
    result1: str = process_value(42)
    result2: str = process_value(3.14)
    result3: str = process_value("hello")
    print(result1, result2, result3)

4.3. Any 类型 #

Any 会跳过静态检查,应谨慎使用,仅在没有更好选择时使用。

# 说明:导入 Any,表示“接受任意类型”
from typing import Any

# 说明:该函数既不约束输入也不约束输出,静态检查无法帮忙
def process_anything(data: Any) -> Any:
    return data

# 说明:脚本入口,展示 Any 会原样返回各种类型
if __name__ == "__main__":
    result1: int = process_anything(10)
    result2: str = process_anything("text")
    result3: list = process_anything([1, 2, 3])
    print(result1, result2, result3)

4.4. Callable 类型 #

用于描述“函数作为参数或返回值”的高阶函数场景。

# 说明:导入 Callable,用于描述函数签名
from typing import Callable, List

# 说明:接收一个加工函数,对整数列表逐个应用
def apply_operation(numbers: List[int], operation: Callable[[int], int]) -> List[int]:
    return [operation(x) for x in numbers]

# 说明:返回一个新的函数,内部携带乘数
def multiplier(factor: int) -> Callable[[int], int]:
    def multiply(x: int) -> int:
        return x * factor
    return multiply

# 说明:脚本入口,展示 lambda 与闭包的用法
if __name__ == "__main__":
    numbers = [1, 2, 3, 4]
    squared = apply_operation(numbers, lambda x: x ** 2)
    double_func = multiplier(2)
    doubled = apply_operation(numbers, double_func)
    print(squared)
    print(doubled)

5. 泛型和类型变量 #

使用类型变量可以让一个函数或类同时适配多种类型,同时保持类型安全。

5.1. TypeVar #

TypeVar 声明一个“类型占位符”,调用时再推断具体类型。

# 说明:导入 TypeVar 与 Sequence 以声明类型变量
from typing import List, Sequence, Tuple, TypeVar

# 说明:声明两个类型变量,分别表示不同的占位类型
T = TypeVar('T')
U = TypeVar('U')

# 说明:函数返回序列的第一个元素,类型与输入保持一致
def first_element(seq: Sequence[T]) -> T:
    return seq[0]

# 说明:函数交换元组中的两个元素,返回的顺序反转
def swap_pair(pair: Tuple[T, U]) -> Tuple[U, T]:
    a, b = pair
    return b, a

# 说明:脚本入口,演示 TypeVar 如何保持类型一致性
if __name__ == "__main__":
    num_list: List[int] = [1, 2, 3]
    first_num: int = first_element(num_list)

    str_list: List[str] = ["a", "b", "c"]
    first_str: str = first_element(str_list)

    swapped: Tuple[str, int] = swap_pair((10, "hello"))
    print(first_num, first_str, swapped)

5.2. 泛型类 #

配合 Generic[T] 可以编写一次代码,支持多种数据类型的容器或工具类。

# 说明:导入 Generic 以构建泛型类
from typing import Generic, List, TypeVar

# 说明:声明类型变量 T,用于表示栈中元素的类型
T = TypeVar('T')

# 说明:泛型栈实现,内部用列表保存元素
class Stack(Generic[T]):
    def __init__(self) -> None:
        self.items: List[T] = []

    # 说明:入栈方法,将元素追加到列表末尾
    def push(self, item: T) -> None:
        self.items.append(item)

    # 说明:出栈方法,返回并移除最后一个元素
    def pop(self) -> T:
        return self.items.pop()

    # 说明:判断栈是否为空
    def is_empty(self) -> bool:
        return len(self.items) == 0

# 说明:脚本入口,演示同一泛型类如何适配不同类型
if __name__ == "__main__":
    int_stack: Stack[int] = Stack()
    int_stack.push(1)
    int_stack.push(2)
    value: int = int_stack.pop()

    str_stack: Stack[str] = Stack()
    str_stack.push("hello")
    text: str = str_stack.pop()
    print(value, text, int_stack.is_empty())

6. 更复杂的类型 #

Literal、Final 与 NewType 可进一步约束取值、声明常量或创建语义更明确的新类型。

6.1. Literal 类型 #

约束参数只能取某几个固定字面值,常用于配置或状态。

# 说明:导入 Literal,用来限定传入的字面值
from typing import Literal

# 说明:该函数只接受正态/停用/待定三个状态
def set_status(status: Literal["active", "inactive", "pending"]) -> None:
    print(f"Status set to: {status}")

# 说明:脚本入口,演示合法与非法的调用方式
if __name__ == "__main__":
    set_status("active")  # 正确
    # set_status("invalid")  # IDE 会提示错误

6.2. Final 类型 #

用于声明常量或不可被子类覆盖的属性,帮助避免误改。

# 说明:导入 Final,用于声明不可变常量
from typing import Final

# 说明:定义两个模块级常量
MAX_SIZE: Final[int] = 100
API_URL: Final[str] = "https://api.example.com"

# 说明:在类中同样可以使用 Final 锁定属性
class Config:
    TIMEOUT: Final[int] = 30

# 说明:脚本入口,读取常量值
if __name__ == "__main__":
    print(MAX_SIZE)
    print(Config.TIMEOUT)

6.3. NewType #

通过为基础类型建立别名,增强类型区分度,减少误用。

# 说明:导入 NewType,用于创建语义化的别名类型
from typing import NewType

# 说明:创建用户 ID 与邮箱类型,底层仍为 int 和 str
UserId = NewType('UserId', int)
Email = NewType('Email', str)

# 说明:函数签名使用自定义类型,避免误传
def get_user_name(user_id: UserId) -> str:
    return f"User_{user_id}"

# 说明:发送邮件函数,要求邮箱类型更安全
def send_email(address: Email, message: str) -> None:
    print(f"Sending to {address}: {message}")

# 说明:脚本入口,展示正确与错误的调用方式
if __name__ == "__main__":
    user_id: UserId = UserId(12345)
    email: Email = Email("user@example.com")

    get_user_name(user_id)  # 正确
    send_email(email, "Hello")  # 正确

    # get_user_name(12345)  # IDE 可能会警告
    # send_email("user@example.com", "Hello")  # IDE 可能会警告

7. 实际应用示例 #

以下示例展示类型提示在真实业务中的写法,方便迁移到自己的项目。

7.1 示例 1:数据处理函数 #

使用 List、Dict、Optional 与 Tuple 表达复杂返回值与可选参数。

# 说明:导入所需的容器类型别名
from typing import Dict, List, Optional, Tuple

# 说明:根据可选过滤条件筛选用户,并返回结果列表与数量
def process_user_data(
    users: List[Dict[str, str]],
    filters: Optional[Dict[str, str]] = None
) -> Tuple[List[Dict[str, str]], int]:
    if filters is None:
        filters = {}

    filtered_users = [
        user for user in users
        if all(user.get(key) == value for key, value in filters.items())
    ]

    return filtered_users, len(filtered_users)

# 说明:脚本入口,传入示例数据并打印筛选结果
if __name__ == "__main__":
    users_data = [
        {"name": "Alice", "role": "admin", "status": "active"},
        {"name": "Bob", "role": "user", "status": "inactive"},
        {"name": "Charlie", "role": "admin", "status": "active"}
    ]

    filtered, count = process_user_data(users_data, {"role": "admin"})
    print(f"Found {count} admin users: {filtered}")

7.2 示例 2:回调系统 #

借助 Callable 与 Any 描述事件回调签名,便于 IDE 发现不匹配。

# 说明:导入 Callable、List 与 Any 构建事件系统
from typing import Any, Callable, List

# 说明:事件处理类,内部维护回调函数列表
class EventHandler:
    def __init__(self) -> None:
        self._callbacks: List[Callable[[Any], None]] = []

    # 说明:注册回调,将函数追加到列表
    def register_callback(self, callback: Callable[[Any], None]) -> None:
        self._callbacks.append(callback)

    # 说明:触发事件,顺序调用所有已注册回调
    def trigger_event(self, data: Any) -> None:
        for callback in self._callbacks:
            callback(data)

# 说明:打印事件数据的回调
def log_callback(data: Any) -> None:
    print(f"Event received: {data}")

# 说明:处理字符串数据的回调,示例包含类型检查
def process_callback(data: Any) -> None:
    if isinstance(data, str):
        print(f"Processing string: {data.upper()}")

# 说明:脚本入口,注册并触发事件
if __name__ == "__main__":
    handler = EventHandler()
    handler.register_callback(log_callback)
    handler.register_callback(process_callback)
    handler.trigger_event("Hello, World!")

8. Python 3.9+ 的新语法 #

在 Python 3.9 及以上版本,可直接使用内置泛型语法(如 list[int])令代码更简洁。

Python 3.9 开始,许多 typing 功能有了更简洁的语法:

# 说明:旧写法需要从 typing 导入 List、Dict 等
from typing import Dict, List

# 说明:对比旧写法与 3.9+ 新语法
def process_data_old(items: List[int]) -> Dict[str, float]:
    return {str(item): float(item) for item in items}

# 说明:使用 3.9+ 新语法的写法
def process_data(items: list[int]) -> dict[str, float]:
    return {str(item): float(item) for item in items}

# 说明:查找集合或列表中的首个元素,返回可选字符串
def find_item(collection: list[str] | set[str]) -> str | None:
    if collection:
        return collection[0] if isinstance(collection, list) else next(iter(collection))
    return None

# 说明:脚本入口,展示新旧写法效果一致
if __name__ == "__main__":
    data_old = process_data_old([1, 2, 3])
    data_new = process_data([1, 2, 3])
    result: str | None = find_item(["a", "b", "c"])
    print(data_old, data_new, result)

9. 总结 #

适度添加类型提示能显著提升代码可维护性,结合静态检查效果更佳。

typing 模块的主要优势:

  1. 提高代码可读性:明确函数参数和返回值的类型
  2. 更好的 IDE 支持:代码补全、错误检查、重构
  3. 早期错误检测:在运行前发现类型相关错误
  4. 便于维护:大型项目中类型提示特别有用
  5. 文档作用:作为代码的补充文档

访问验证

请输入访问令牌

Token不正确,请重新输入