簡體   English   中英

使用 Python 3.6 在運行時獲取通用類型的 class

[英]Get generic type of class at runtime with Python 3.6

遵循此問題中描述的解決方案: How to access 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]獲取其基本 class ,這給了我沒有通用 arguments 的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]

dataclasses 3.6 還需要將數據類安裝為庫,盡管它不是此問題的一部分。 另請注意, __args__似乎在 Python 3.6 中沒有記錄,並從 Python 3.8 中刪除。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM