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

如何为Python运行时动态创建的类添加类型提示?

问题:如何为动态生成数据类的SQLite包装类添加类型提示?

我编写了一个用于管理SQLite数据库连接的简单包装类,借助row_factory和recordclass让查询结果的每一行都以运行时动态生成的数据类实例形式返回。代码如下:

import sqlite3
import recordclass

class DBConnection:
    def __init__(self, file_path):
        self.connection = sqlite3.connect(file_path)
        self.connection.row_factory = self.make_row_factory(
            recordclass.make_dataclass,
            fast_new=True,
        )
        self.cursor = self.connection.cursor()

    def make_row_factory(self, cls_factory, **kw):
        def row_factory(cursor, row, cls=[None]):
            rf = cls[0]
            if rf is None:
                fields = [col[0] for col in cursor.description]
                cls[0] = cls_factory("Row", fields, **kw)
                return cls[0](*row)
            return rf(*row)
        return row_factory

    def query(self, query: str):
        result = self.cursor.execute(query)
        return result.fetchall()

目前遇到的核心问题:

  • 无法直接为query方法添加返回类型提示(即def query(self, query: str) -> list[????]),因为生成的数据类仅在运行时存在
  • make_row_factory和内部的row_factory方法的类型提示也存在同样的挑战

解决方案

1. 用泛型+TypeVar实现动态类型支持

这是最严谨的方案,能让类型检查器识别动态行类型的结构:

首先导入所需类型模块,定义泛型类型变量并让DBConnection继承Generic:

import sqlite3
import recordclass
from typing import TypeVar, Generic, List, Callable, Any, Tuple, Optional

RowT = TypeVar("RowT")

class DBConnection(Generic[RowT]):

然后修改query方法的类型提示:

def query(self, query: str) -> List[RowT]:
    result = self.cursor.execute(query)
    return result.fetchall()

使用者可以在实例化时手动指定预期的行类型(比如提前定义对应表结构的dataclass),类型检查器也能通过上下文自动推断类型。

2. 为工厂方法添加类型提示

针对make_row_factory和内部的row_factory,可以用Callable描述函数签名,结合泛型变量标记动态类型:

def make_row_factory(
    self,
    cls_factory: Callable[[str, List[str], Any], type[RowT]],
    **kw: Any
) -> Callable[[sqlite3.Cursor, Tuple[Any, ...]], RowT]:
    def row_factory(
        cursor: sqlite3.Cursor,
        row: Tuple[Any, ...],
        cls: List[Optional[type[RowT]]] = [None]
    ) -> RowT:
        rf = cls[0]
        if rf is None:
            fields = [col[0] for col in cursor.description]
            cls[0] = cls_factory("Row", fields, **kw)
            return cls[0](*row)
        return rf(*row)
    return row_factory

说明:

  • cls_factory的类型描述:接收类名、字段列表、关键字参数,返回一个RowT类型的类
  • 返回的row_factory类型描述:接收游标和行数据元组,返回RowT实例

3. 简化方案:直接使用Any

如果不需要严格的类型检查,用Any可以快速完成类型提示,适合快速开发场景:

from typing import List, Any

def query(self, query: str) -> List[Any]:
    result = self.cursor.execute(query)
    return result.fetchall()

这种方式最简洁,但会丢失类型检查的优势,仅建议在小型项目或原型开发中使用。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.12 21:05:09