Я просматривал раздел PEP 484 в разделе Forward References и заметил заявление:
... это определение может быть выражено как строковый литерал, который будет разрешен позже.
И это заставило меня задуматься, когда «позже» и чем? Интерпретатор не пытается разрешить его как литерал позже, так что же делать? Это просто, если для этого написан сторонний инструмент?
Небольшой пример для демонстрации результата интерпретатора:
class A:
def test(self, a: 'A') -> None:
pass
class B:
def test(self, a: A) -> None:
pass
>>> A().test.__annotations__
{'a': 'A', 'return': None}
>>> B().test.__annotations__
{'a': <class '__main__.A'>, 'return': None}
Если мое понимание аннотаций функций и подсказок типов правильное, Python на самом деле не ничего делает с ними во время выполнения для повышения производительности, а, скорее, интроспективное использование позволяет строго третьей стороне приложения, такие как линтеры, IDE и инструменты статического анализа (такие как mypy
), чтобы воспользоваться их доступностью. Так будут ли эти инструменты пытаться разрешить подсказку типа 'A'
вместо того, чтобы возлагать эту работу на интерпретатор, и если да, то как они это делают?
Обновление:
С помощью модуля typing
пользовательский код может выполнять следующие действия:
>>> typing.get_type_hints(A().test)
{'a': <class '__main__.A'>, 'return': <class 'NoneType'>}
>>> typing.get_type_hints(B().test)
{'a': <class '__main__.A'>, 'return': <class 'NoneType'>}
Однако мой вопрос направлен на то, несет ли Python какую-либо ответственность за обновление __annotations__
функции из строкового литерала, то есть при изменении времени выполнения:
>>> A().test.__annotations__
{'a': 'A', 'return': None}
to...
>>> A().test.__annotations__
{'a': <class '__main__.A'>, 'return': None}
Если Python этого не делает, то зачем мне строковый литерал в качестве подсказки типа, кроме самодокументированного кода? Какую ценность дает мне первая форма, пользователю или стороннему инструменту?