Какая аннотация типа Python для представления класса универсального типа - PullRequest
0 голосов
/ 06 ноября 2019

В моем коде Python 3.7.4 у меня есть следующая функция.

def is_dict(klass: ???) -> bool:
    return klass.__origin__ == dict

Я изо всех сил пытаюсь получить правильную аннотацию типа для параметра klass. Это не type, для этого mypy жалуется.

ошибка: "type" не имеет атрибута "__origin__"

Я в растерянности,Что такое правильная аннотация и есть ли хорошая документация по этому поводу?

Вот пример использования этой функции:

>>> is_dict(typing.Dict[str, int])
True
>>> is_dict(typing.List[str])
False

Ответы [ 2 ]

1 голос
/ 10 ноября 2019

Если вы хотите использовать что-то вроде GenericMeta, как предлагается в комментариях, или попытаться поэкспериментировать с созданием пользовательского протокола , который определяет соответствующий атрибут __origin__, вам сначала необходимо обновитьподсказки для модуля ввода в typhed , чтобы определить эти атрибуты.

Однако сейчас я рекомендую использовать только Type[Any] или Type[object].

from typing import Type, Any

# If you want to make minimal modifications to your code, make
# 'klass' dynamically typed.
def is_dict_1(klass: Type[Any]) -> bool:
    return klass.__origin__ == dict

# If you want to make your code robust, assume nothing about 'klass'
# except that it's some sort of type and verify the attribute you're
# about to use exists.
def is_dict_2(klass: Type[object]) -> bool:
    return getattr(klass, '__origin__', None) == dict

Если вы специально пытаетесь напрямую манипулировать выражениями подсказок типов, потому что вы пытаетесь создать какую-то библиотеку сериализации / десериализации, вы также можете попробовать взглянуть на исходный код библиотек, например pydantic длявдохновение.

Чуть шире, я бы также рекомендовал вам изучить возможность минимизации мест в вашем коде, где вы по возможности манипулируете выражениями подсказок типов как объектами времени выполнения. Экосистема типирования Python была в значительной степени разработана для того, чтобы разделить статический и исполняемый мир, поэтому механизмы для смешения двух миров не очень удобны в использовании и не всегда имеют обратную совместимость. Например, внутренняя часть библиотеки набора текста менялась несколько раз с момента ее первого выпуска в Python 3.5.

0 голосов
/ 06 ноября 2019

Я отредактировал ответ:

import typing

def is_dict(klass: typing.GenericMeta) -> bool:
    return klass.__origin__ == typing.Dict

if __name__ == "__main__":
    print(is_dict(typing.Dict[str, int]))
    print(is_dict(typing.List[str]))

В качестве альтернативы:

def is_dict(klass: typing.GenericMeta) -> bool:
        return klass.__orig_bases__[0] == dict
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...