如何在Python中获取类的GenericAlias类型父类?
获取泛型类的具体化父类型(如list[int])的方案
当你定义了继承自具体化泛型的类(比如class MyList(list[int]): ...),普通的inspect.getmro()只能返回泛型类本身(如list),无法拿到带参数的list[int]。以下是不用源码解析的可行方案:
1. 直接访问__orig_bases__属性
PEP 560引入了__orig_bases__属性,专门存储类定义时声明的原始泛型基类,这是最直接的方式:
from typing import List class MyList(List[int]): pass print(MyList.__orig_bases__) # 输出: (typing.List[int],)
这个属性会返回类定义时写的所有泛型基类元组,完全符合你需要的list[int]这类具体化类型。
2. 封装通用工具函数
如果需要兼容更多场景(比如无泛型参数的普通基类、多层继承),可以封装一个工具函数来处理:
from typing import GenericAlias, get_origin, get_args def get_super_generics(cls): """获取类的具体化泛型父类,兼容普通基类""" supers = [] # 优先读取原始泛型基类 if hasattr(cls, '__orig_bases__'): supers.extend(cls.__orig_bases__) else: # 没有泛型参数时读取普通基类 supers.extend(cls.__bases__) # 可选:递归处理父类的泛型(比如多层继承场景) processed_supers = [] for base in supers: if isinstance(base, type) and hasattr(base, '__orig_bases__'): # 如果父类本身也是泛型子类,递归获取其原始基类 processed_supers.extend(get_super_generics(base)) else: processed_supers.append(base) return processed_supers # 测试多层继承 class MySubList(MyList): pass print(get_super_generics(MySubList)) # [typing.List[int]]
3. 结合你的通用issubtype需求
针对你要实现的通用类型判断逻辑,需要结合typing模块的get_origin和get_args来拆解泛型类型,核心思路是:
- 对比泛型的原始类型(比如
list[int]的原始类型是list) - 对比泛型的参数(比如
list[int]的参数是(int,))
以下是一个简化版的通用issubtype实现:
def is_subtype(t1, t2): """判断t1是否是t2的子类型,支持泛型别名和自定义泛型类""" # 处理t2是泛型别名的情况 if isinstance(t2, GenericAlias): t2_origin = get_origin(t2) t2_args = get_args(t2) # 如果t1是自定义类,检查其原始泛型基类 if isinstance(t1, type): for base in get_super_generics(t1): if isinstance(base, GenericAlias): base_origin = get_origin(base) base_args = get_args(base) if base_origin is t2_origin and base_args == t2_args: return True # 同时兼容判断是否是泛型类本身的子类(比如MyList是list的子类) return issubclass(t1, t2_origin) # 如果t1也是泛型别名,直接对比原始类型和参数 if isinstance(t1, GenericAlias): t1_origin = get_origin(t1) t1_args = get_args(t1) return t1_origin is t2_origin and t1_args == t2_args # 处理普通类的继承判断 if isinstance(t1, type) and isinstance(t2, type): return issubclass(t1, t2) return False # 测试用例 print(is_subtype(MyList, List[int])) # True print(is_subtype(MySubList, List[int])) # True print(is_subtype(List[int], List[int])) # True print(is_subtype(MyList, List)) # True print(is_subtype(List[str], List[int])) # False
注意事项
__orig_bases__是PEP 560规范的属性,主流Python实现(CPython、PyPy)都支持,但动态创建的类(比如用type()函数生成)可能没有这个属性,需要额外处理。- 对于泛型类本身(比如
List而非List[int]),__orig_bases__不存在,此时会 fallback 到普通的__bases__属性。
内容的提问来源于stack exchange,提问作者mattg
相关产品推荐
相关产品推荐

