如何从自定义类型提示CustomParameter中获取泛型参数Sunshine?
问题描述
我写了一个简单的泛型类CustomParameter:
from typing import TypeVar, Generic T = TypeVar('T') class CustomParameter(Generic[T]): def __init__(self, value: T) -> None: print(value, T) self.value = value def get(self) -> T: print(self.value) return self.value
之后在函数的类型注解里用了带字符串类型参数的泛型:
def is_dark(x: CustomParameter['Sunshine']) -> int: return x
现在我想从CustomParameter['Sunshine']这个类型注解里提取出'Sunshine'对应的实际类型,用来检查输入x的value是不是真的Sunshine类型的对象,请问该怎么实现?
解决方案
要提取泛型类型注解里的类型参数,你可以用Python标准库的typing.get_args()、typing.get_origin(),再结合inspect模块来解析函数的参数注解。下面是具体的实现步骤和代码:
步骤1:获取函数的参数注解
先用inspect.signature()拿到目标函数的签名,然后就能取出对应参数的类型注解。
步骤2:解析泛型类型
用get_origin()确认注解是CustomParameter的泛型实例,再用get_args()提取里面的类型参数(也就是你写的'Sunshine')。
步骤3:映射到实际类型
因为你用的是字符串形式的类型名,需要把它转换成当前作用域里的实际类对象。
完整的示例代码如下:
import inspect from typing import get_args, get_origin from typing import TypeVar, Generic T = TypeVar('T') class CustomParameter(Generic[T]): def __init__(self, value: T) -> None: print(value, T) self.value = value def get(self) -> T: print(self.value) return self.value # 先定义你的Sunshine类(假设这是你实际要用的类型) class Sunshine: pass def is_dark(x: CustomParameter['Sunshine']) -> int: return x # 封装一个提取泛型参数的工具函数 def extract_generic_type(func, param_name): # 获取函数的签名信息 sig = inspect.signature(func) # 拿到目标参数的类型注解 param_anno = sig.parameters[param_name].annotation # 先确认这个注解是CustomParameter的泛型实例 if get_origin(param_anno) is CustomParameter: # 提取泛型的类型参数,得到('Sunshine',)这样的元组 generic_args = get_args(param_anno) # 取出第一个参数(因为我们的泛型只有一个类型变量T) type_str = generic_args[0] # 从全局作用域中获取对应的实际类型 actual_type = globals().get(type_str) return actual_type return None # 测试一下提取结果 target_type = extract_generic_type(is_dark, 'x') print(target_type) # 会输出 <class '__main__.Sunshine'> # 现在就可以用这个类型来检查输入了 test_param = CustomParameter(Sunshine()) if isinstance(test_param.get(), target_type): print("输入的value确实是Sunshine类型的对象") else: print("输入的value不是Sunshine类型")
几个关键点说明:
get_origin():这个函数会返回泛型的原始类,比如这里的CustomParameter,用来确保我们处理的是正确的泛型类型,避免误解析其他注解。get_args():返回泛型的类型参数元组,这里因为我们的泛型只有一个类型变量T,所以取第一个元素就好。globals().get(type_str):如果你的Sunshine类在其他模块里,那你需要换成从对应模块的__dict__里获取,或者用importlib来动态导入,确保能拿到实际的类对象。
另外要注意,这个方案是针对运行时提取类型参数的,如果是在静态类型检查阶段(比如用mypy),处理逻辑会不一样,但日常运行时的类型校验需求,这个方法完全够用。
内容的提问来源于stack exchange,提问作者code base 5000
相关产品推荐
相关产品推荐

