С помощью PEP 563 from __future__ import annotations
изменяет аннотации типов так, чтобы они оценивались лениво, что обеспечивает множество преимуществ, таких как прямые ссылки.
Однако это плохо работает с другими функциями, такими как классы данных. Например, у меня есть некоторый код, который проверяет параметры типа метода класса __init__
. (Реальный вариант использования - предоставить сериализатор по умолчанию для класса, но это здесь не важно.)
from dataclasses import dataclass
from typing import get_type_hints
class Foo:
pass
@dataclass
class Bar:
foo: Foo
print(get_type_hints(Bar.__init__))
В Python 3.6 и 3.7 это делает то, что ожидается; печатает {'foo': <class '__main__.Foo'>, 'return': <class 'NoneType'>}
.
Однако, если в Python 3.7 я добавлю from __future__ import annotations
, произойдет сбой с ошибкой:
NameError: name 'Foo' is not defined
Мне кажется, я понимаю, почему это происходит. Метод __init__
определен в dataclasses
, который не имеет объекта Foo
в своем окружении, а аннотация Foo
передается в dataclass
и присоединяется к __init__
в виде строки "Foo"
. чем исходный объект Foo
, но get_type_hints
для новых аннотаций выполняет поиск имени только в модуле, где __init__
определяется не там, где аннотация.
Мне кажется, что я что-то делаю не так. Я удивлен, что эти две новые функции играют так плохо вместе. Есть ли правильный способ проверки подсказок типа метода __init__
, чтобы он работал с классами данных так же, как с обычными классами?