如何正确注解使用CPython PySequence_Check的C扩展Python函数?
适配PySequence_Check的类型注解方案
方案1:自定义Protocol + 运行时检查
既然PySequence_Check的逻辑是「有__getitem__且不是dict/子类」,可以先定义一个匹配该特征的Protocol,同时在函数里补充运行时检查,和C扩展的验证逻辑对齐:
from typing import Protocol, TypeVar, Any from collections.abc import Mapping T = TypeVar('T') class PySequenceLike(Protocol[T]): def __getitem__(self, index: int) -> T: ... def my_c_func(my_sequence: PySequenceLike[Any]): # 补充运行时检查,和PySequence_Check逻辑一致 if isinstance(my_sequence, Mapping): raise TypeError("dict或其子类不被允许") # 调用C扩展逻辑 ...
这个方案的优势:
- 静态类型检查工具(如mypy)会识别出拥有
__getitem__的类型,匹配PySequence_Check的核心要求 - 运行时检查和C扩展的验证逻辑完全对齐,避免静态注解与实际校验的偏差
- 基于标准库实现,无需额外依赖
方案2:显式列举支持的序列类型
如果你的场景中,函数仅需处理几种常见序列类型(比如list、tuple、str、bytes等),可以直接用Union显式标注:
from typing import Union def my_c_func(my_sequence: Union[list, tuple, str, bytes]): ...
这个方案的优点是类型提示非常明确,缺点是无法覆盖所有自定义的、符合PySequence_Check标准的序列类型,灵活性较差。
方案3:注释补充说明(最简方案)
如果不需要严格的静态类型检查,也可以保留Sequence注解,同时用注释明确实际的验证逻辑:
from typing import Sequence, Any def my_c_func(my_sequence: Sequence[Any]): """ 接收符合PySequence_Check标准的序列:拥有__getitem__且不是dict/子类 """ ...
这种方式简单直接,但依赖开发者阅读注释,静态检查工具无法识别实际的类型限制。
内容的提问来源于stack exchange,提问作者oBrstisf8o
相关产品推荐
相关产品推荐

