Mypy отвергает объекты типа, созданные с помощью ' type (name, (bases,), {}) `


У меня возникли некоторые проблемы с тем, чтобы заставить mypy принимать объекты типа. Я убежден, что я просто делаю это неправильно, но мои поиски в google не привели меня ни к каким ответам до сих пор.

class Good(object):
    a = 1

def works(thing: Good):
    print(thing.a)

o = Good()
works(o)

Bad = type('Bad', (object, ), dict(a=1))

def fails_mypy(thing: Bad):
    print(thing.a)

s = Bad()
fails_mypy(s)

Вещи, построенные как ' Good', в порядке, в то время как вещи, построенные как ' Bad', не проходят проверку mypy с помощью:

error: Invalid type "test.Bad"
error: Bad? has no attribute "a"
1 2

1 ответ:

Основываясь на разделенеподдерживаемых функций Python Вики mypys, создание таких классов во время выполнения в настоящее время не поддерживается. Он не может понять, что Bad находится в определении вашей функции. Использование reveal_type(Good) и reveal_type(Bad) при выполнении mypy должно прояснить это.

Подход к их замалчиванию заключается в использовании Any. Либо с помощью синтаксиса аннотаций переменных Python 3.6:

Bad: Any = type('Bad', (), {'a':1})

Или, с Python

Bad = type('Bad', (), {'a':1}) # type: Any

(в обоих случаях Any следует во первых быть импортированным от typing)

Конечно, это в основном означает, что ваша функция теперь принимает все, что угодно. Цена, которую нужно заплатить, но это то, что вы получаете с динамическими языками; так как Bar определяется во время выполнения, это может теоретически быть чем угодно : -)