如何为动态创建的类实现动态类型提示?
问题分析与解决方案
核心原因
静态类型检查器(比如mypy、Pyright)是静态分析代码,不会执行运行时的动态逻辑。你在create()函数内部定义的TD TypedDict、动态修改的__annotations__,以及用type()创建类的过程,都是运行时才会发生的操作,类型检查器在分析代码时根本看不到这些细节,自然无法提供正确的类型提示。
可行解决方案
要让类型提示生效,必须把需要类型检查的结构暴露在静态分析能覆盖到的范围(比如模块级别),再通过类型断言告诉检查器动态创建的类符合预期结构。
步骤1:定义模块级别的类型协议和TypedDict
先在模块顶部定义好Child类需要的参数结构和属性协议:
from typing import Type, cast, Unpack, TypedDict, Protocol class Base: def __init__(self, **kwargs: object) -> None: pass # 模块级别定义__init__的参数结构 class ChildInitTD(TypedDict): first: int second: str # 定义Child类应该符合的协议(包含属性和构造方法) class ChildProtocol(Protocol): a: int b: str def __init__(self, **kwargs: Unpack[ChildInitTD]) -> None: ...
步骤2:修改create函数,用类型断言返回协议类型
调整create()函数,返回时用cast告诉类型检查器,动态创建的类符合ChildProtocol:
def create() -> Type[ChildProtocol]: def __init__(self, **kwargs: Unpack[ChildInitTD]): setattr(self, 'a', kwargs['first']) setattr(self, 'b', kwargs['second']) return cast(Type[ChildProtocol], type('Child', (Base,), {'__init__': __init__, '__annotations__': {'a': int, 'b': str}}))
验证效果
这样之后,类型检查器就能识别:
Child的构造方法必须传入first:int和second:str的关键字参数Child实例的a属性是int类型,b是str类型
为什么原代码不行?
你原代码里的操作都是运行时动态修改,比如在函数内部定义TD、修改__init__.__annotations__,这些信息只有程序运行起来才存在,静态类型检查器不会执行create()函数来获取这些类型细节,所以完全无法识别。
内容的提问来源于stack exchange,提问作者Federico Pirani
相关产品推荐
相关产品推荐

