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

Python中如何让动态导入类的create函数具备类型感知?

解决动态导入WebSocket流类的类型感知问题

要让create函数具备类型感知,让类型检查工具(如mypy、PyCharm)能正确推断返回实例的类型,可以通过以下步骤实现:

1. 导入类型工具并定义约束

在stream.py中导入Python标准库的类型注解工具,同时明确所有支持的流类与对应名称:

from typing import Type, TypeVar, Literal, Dict
from feeds.AbstractStream import AbstractStream
# 导入所有已实现的WebSocket流类
from feeds.streams import binanceusdm, okx, bybit  # 示例,根据实际类添加

# 定义TypeVar,绑定到AbstractStream的子类,确保返回类型合法
StreamSubclass = TypeVar("StreamSubclass", bound=AbstractStream)

# 用Literal限定允许传入的流名称,类型检查工具会提示非法输入
SupportedStreamNames = Literal["binanceusdm", "okx", "bybit"]

# 创建名称到流类的映射,替代getattr,提升安全性和类型推断能力
STREAM_CLASS_MAP: Dict[SupportedStreamNames, Type[AbstractStream]] = {
    "binanceusdm": binanceusdm,
    "okx": okx,
    "bybit": bybit,
}

2. 改造create函数的实现与类型注解

修改create函数,使用上述映射替代getattr,并添加精确的类型注解:

def create(param: SupportedStreamNames) -> Type[StreamSubclass]:
    try:
        stream_cls = STREAM_CLASS_MAP[param]
    except KeyError as e:
        raise AttributeError(f"Unknown stream: {param}") from e
    return stream_cls

效果说明

现在调用代码时:

s = stream.create("binanceusdm")()

类型检查工具会自动推断出s的类型是binanceusdm实例,而非Any;同时传入非法流名称时,会提前给出类型错误提示。

可选优化:自动注册子类

如果后续会新增大量交易所流类,手动维护映射繁琐,可以用装饰器自动注册子类:

# 初始化空的映射
STREAM_CLASS_MAP: Dict[str, Type[AbstractStream]] = {}

def register_stream(name: str):
    def decorator(cls: Type[AbstractStream]):
        STREAM_CLASS_MAP[name] = cls
        return cls
    return decorator

在每个流类文件中使用装饰器注册:

from feeds.AbstractStream import AbstractStream
from feeds.stream import register_stream

@register_stream("binanceusdm")
class binanceusdm(AbstractStream):
    # 类实现...

注:自动注册后需手动维护SupportedStreamNames的Literal类型,才能保留严格的类型检查能力。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 01:27:56