You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为动态创建的Python类方法添加类型注解

类型注解优化方案

先修正原代码的一个潜在问题:request方法中data: dict = {}使用了可变对象作为默认参数,多次调用时若修改data会影响后续请求,建议改成:

def request(self, method: str, path: str, data: dict | None = None, files: dict | None = None) -> Response:
    data = data or {}
    # 原请求逻辑代码

下面是完整的类型注解优化方案,让send_test、send_start这类动态方法能被静态检查器识别,且仅接受data和files参数:

完整代码示例

from typing import TypedDict, Optional, Callable, TYPE_CHECKING

# 定义响应结构类型
class Response(TypedDict):
    status: int
    content: str  # 示例字段,根据实际业务调整

# 路由映射配置
ROUTES = {
    "send_test": ["GET", "/test/"],
    "send_start": ["GET", "/start/"]
}

# 定义动态请求方法的类型别名:接受data和files,返回Response
RequestAlias = Callable[[dict, Optional[dict]], Response]

# 仅在静态类型检查时生效,告知检查器Client类存在这些动态方法
if TYPE_CHECKING:
    class Client:
        send_test: RequestAlias
        send_start: RequestAlias

class Client(object):
    def __init__(self) -> None:
        for mname, (method, path) in ROUTES.items():
            setattr(self, mname, self.make_request_func(method, path))

    def make_request_func(self, method: str, path: str) -> RequestAlias:
        # 给闭包明确标注参数和返回值类型
        def _func(data: dict = {}, files: Optional[dict] = None) -> Response:
            return self.request(method, path, data, files)
        return _func

    def request(self, method: str, path: str, data: dict = {}, files: Optional[dict] = None) -> Response:
        # 实际请求逻辑,示例返回值
        return {"status": 200, "content": "OK"}

关键注解解释

  1. RequestAlias类型别名
    用Callable[[dict, Optional[dict]], Response]统一定义动态方法的签名:接受data(字典)和files(可选字典)两个参数,返回Response类型,避免重复写复杂的Callable类型。

  2. TYPE_CHECKING条件块
    TYPE_CHECKING是运行时为False的常量,仅静态检查器(如mypy)会解析这块代码。在这里给Client类添加动态方法的类型声明,让检查器识别这些方法的存在和签名,不会抛出“属性未定义”的错误。

  3. 闭包_func的注解
    给动态生成的函数明确标注参数和返回值类型,既保证和RequestAlias类型匹配,也让静态检查器能识别该函数的参数要求。

  4. request方法的参数注解
    给method、path添加str类型注解,明确必填参数类型;files用Optional[dict]标注,表示该参数可以为None或字典。

批量路由的简化优化

如果后续路由会频繁新增,手动在TYPE_CHECKING块添加方法注解太繁琐,可以用__getattr__自动处理:

from typing import Any

class Client(object):
    def __getattr__(self, name: str) -> RequestAlias:
        if name in ROUTES:
            method, path = ROUTES[name]
            return self.make_request_func(method, path)
        raise AttributeError(f"Client has no attribute '{name}'")

    # 其他方法保持不变...

这样静态检查器会通过__getattr__的返回值类型,自动识别所有ROUTES中的方法都符合RequestAlias签名,无需逐个添加注解。

内容的提问来源于stack exchange,提问作者itekhi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 01:50:27