如何在Python中基于类方法名实现静态Literal类型提示
Python静态类型检查:约束类方法名字面量输入
摘要(TL;DR)
class SomeClass: def some_method(self): pass # 替换后的代码 from typing_extensions import KeyOf methods_names_type = KeyOf[SomeClass] # 类型检查工具会将其识别为 typing.Literal["some_method", ...](包含类的所有方法/属性名)
详细需求
我有一个函数my_func,接收两个参数:一个类(非实例),以及由该类方法名字面量字符串组成的列表。要求当传入不存在的方法名时,类型检查工具(如mypy)能触发报错。
现有基础代码:
def my_func(cls, cls_methods_names): ...
以SomeClass为例,调用时传入不存在的non_existent应触发类型错误:
my_func(SomeClass, [ "some_method" , "non_existent" # 此处类型检查应报错 ] )
当前已写出的类型标注框架:
T = TypeVar("T") def my_func(cls: Type[T], cls_methods_names: list[<???>]): ...
需要替换<???>,实现类似静态版dir(T)的功能,即在静态类型检查阶段获取类的方法名并用于输入约束,请问是否可行?
TypeScript参考实现逻辑
在TypeScript中,可以通过keyof操作符结合类型过滤,实现对类方法名字面量的静态检查。编译器会自动识别非法的方法名字符串并抛出错误,所有校验都在静态阶段完成。
解决方案
可以通过typing_extensions库中的KeyOf类型(Python 3.12+可直接使用typing.KeyOf)来实现需求,它能静态获取类的所有属性/方法名作为字面量类型集合:
from typing import TypeVar, Type, List from typing_extensions import KeyOf # Python 3.12+ 替换为 from typing import KeyOf T = TypeVar("T") def my_func(cls: Type[T], cls_methods_names: List[KeyOf[T]]): ...
说明
KeyOf[T]会被类型检查工具(如mypy、pyright)解析为类T的所有公共属性和方法名的字面量联合类型,比如对于SomeClass,它等价于Literal["some_method", "__init__", "__str__", ...](包含类的内置方法)。- 如果需要仅保留自定义方法(排除内置特殊方法),可以结合
typing.Literal手动筛选,或者通过自定义Protocol来约束,但这需要额外的类型定义。 - 该方案依赖类型检查工具对
KeyOf的支持,确保使用的工具(如mypy)版本足够新。
内容的提问来源于stack exchange,提问作者EL96NG8C NG
相关产品推荐
相关产品推荐

