J'Blog

16 课 · 进阶

语义检索

基于 Chroma 向量库,与 Workspace 知识库分离。用自然语言描述你想查的内容。 非管理员每人每天可检索 5 次(消耗站点 AI 配额)。

Python类型提示系统

原文:typing 类型标注

一句话

Python类型提示系统,用于静态类型检查和代码文档。

什么时候翻这页

  1. 需要为函数和类添加类型提示以提高代码可读性
  2. 使用泛型类型创建灵活的数据结构
  3. 定义协议(Protocol)实现结构化输出,用于Agent工具返回类型
  4. 标注异步函数和生成器,用于处理Agent的异步操作

核心概念

  1. 类型别名:使用type关键字或TypeAlias为复杂类型创建简短名称
  2. NewType:创建特定类型的新子类型,增强类型安全性
  3. 泛型(Generic):使用TypeVar创建可重用的类型参数化类和函数
  4. 协议(Protocol):定义结构化接口,用于实现鸭子类型
  5. 特殊类型:如AnyUnionLiteral等用于特殊场景的类型
  6. 类型守卫和类型收窄:使用TypeGuardTypeIs进行类型检查和收窄
  7. 参数规范(ParamSpec):用于标注可变参数和关键字参数的类型

怎么做

  1. 基本类型标注
def surface_area_of_cube(edge_length: float) -> str:
    return f"The surface area of the cube is {6 * edge_length ** 2}."
  1. 创建类型别名
type Vector = list[float]

def scale(scalar: float, vector: Vector) -> Vector:
    return [scalar * num for num in vector]
  1. 使用NewType创建特定类型
from typing import NewType

UserId = NewType('UserId', int)
some_id = UserId(524313)

def get_user_name(user_id: UserId) -> str:
    return f"User {user_id}"
  1. 定义泛型类
from typing import TypeVar, Generic

T = TypeVar('T')

class LoggedVar(Generic[T]):
    def __init__(self, value: T, name: str) -> None:
        self.value = value
        self.name = name
    
    def set(self, new: T) -> None:
        print(f"Setting {self.name} from {self.value} to {new}")
        self.value = new
    
    def get(self) -> T:
        print(f"Getting {self.name}: {self.value}")
        return self.value
  1. 定义协议
from typing import Protocol

class Combiner(Protocol):
    def __call__(self, *vals: bytes, maxlen: int | None = None) -> list[bytes]: ...

def batch_proc(data: list[bytes], cb_results: Combiner) -> bytes:
    # 处理数据
    pass
  1. 标注异步函数
from collections.abc import AsyncGenerator

async def infinite_stream(start: int) -> AsyncGenerator[int]:
    while True:
        yield start
        start += 1

命令 / API 速查

类型/函数描述
Any表示任意类型
Union[X, Y]表示X或Y类型
Optional[X]表示X或None类型
List[X]表示X类型的列表
Dict[K, V]表示键为K类型,值为V类型的字典
Tuple[X, Y]表示X和Y类型的元组
Callable[[X], Y]表示接受X类型参数并返回Y类型的可调用对象
Generator[X, Y, Z]表示生成器,产生X类型,接受Y类型,返回Z类型
AsyncGenerator[X, Y]表示异步生成器
Protocol定义协议接口
TypeVar定义类型变量
NewType创建新类型
TypeGuard类型守卫函数
TypeIs类型判断函数
ParamSpec参数规范类型变量
Concatenate连接参数规范
Final标记不可重写或不可重新赋值的属性
ClassVar标记类变量
Literal表示字面值类型
TypedDict表示类型化字典
Annotated带有额外元数据的类型
assert_type断言变量为特定类型
reveal_type显示变量的推断类型
cast类型转换
get_type_hints获取对象的类型提示
get_origin获取类型的原始类型
get_args获取类型的参数

与 Agent 开发的联系

  1. 工具返回类型标注:使用TypedDictProtocol为Agent工具定义结构化返回类型,确保返回的数据符合预期格式
  2. 异步操作处理:使用AsyncGeneratorAwaitable标注Agent的异步操作,如流式响应处理
  3. 类型安全工具调用:通过类型提示确保Agent工具调用的参数类型正确,减少运行时错误

初学者易错点

  1. 混淆类型变量和具体类型TypeVar是类型变量,不是具体类型,不能直接用作类型注解
  2. 过度使用Any:虽然Any很方便,但过度使用会失去类型检查的好处
  3. 忽略类型守卫的作用域TypeGuardTypeIs只在函数内部有效,不会改变外部变量的类型
  4. 错误使用泛型约束:泛型约束(bound, covariant, contravariant)使用不当会导致类型检查错误
  5. 前向引用未正确处理:在类定义中使用尚未定义的类型时,需要使用字符串形式或ForwardRef

相关词条

  • library-dataclasses - 数据类,与类型提示结合使用
  • library-contextlib - 上下文管理器,与类型提示结合使用
  • library-asyncio - 异步编程,与类型提示结合使用
  • library-json - JSON数据处理,与类型提示结合使用
  • library-pydantic - 数据验证库,基于类型提示
  • library-mypy - 静态类型检查器

官方原文:https://docs.python.org/zh-cn/3/library/typing.html