遵循此问题中描述的解决方案:How to access the type arguments of typing.Generic?
我已经在 Python 3.8 中成功解决了运行时的泛型问题。但是,我似乎无法访问 Python 3.6 解决方案中描述的 __args__
字段。我不确定为什么,这是我的代码:
def get_generic_type_arg(cls):
if py_version >= (3, 8):
t = cls.__orig_bases__[0]
return get_args(t)[0]
else:
t = cls.__args__
return None
class EventContract:
@classmethod
def get_version(cls) -> int:
return int(cls.__name__[1:])
RT = TypeVar('RT', bound=EventContract)
class QueryContract(Generic[RT], EventContract):
""" Base class for query contracts that are versioned. """
@classmethod # Do not override this
def get_response_class(cls) -> Type[RT]:
return get_generic_type_arg(cls)
def build_result(self, *args, **kwargs):
return self.get_response_class()(**kwargs)
@dataclasses.dataclass
class V1Response(EventContract):
value: int
@dataclasses.dataclass
class V1(QueryContract[V1Response]):
id: int
name: str
当尝试在 cls
上调用 get_generic_type
时,我得到一个 AttributeError
。我还尝试使用 t.__bases__[0]
获取它的基类,这给了我没有通用参数的 QueryContract
(__args__
给了我另一个属性错误)。我在 V1
上调用 get_response_class
方法。有什么想法吗?
最佳答案
我已经想好了怎么做。出于某种原因,__orig_bases__
无法正常工作,但在重建我的 Python 3.6 并使用 VENV 后,它可以正常工作。这是最终的工作方法:
py_version = sys.version_info
if py_version >= (3, 8):
from typing import get_args
def get_generic_type_arg(cls):
t = cls.__orig_bases__[0]
if py_version >= (3, 8):
return get_args(t)[0]
else:
return t.__args__[0]
Python 3.6 还需要安装 dataclasses
作为一个库,尽管它不是这个问题的一部分。另请注意,__args__
似乎未在 Python 3.6 中记录并从 Python 3.8 中删除。
关于python - 使用 Python 3.6 在运行时获取类的通用类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70338370/