I was looking at the PEP 484 section on Forward References and noticed the statement:
...that definition may be expressed as a string literal, to be resolved later.
And that got me wondering, when is "later" and by what? The interpreter doesn't try to resolve it as a literal later, so what does? Is it just if a third party tool is written to do that?
Small example to demonstrate the interpreter result:
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}
If my understanding of function annotations and type hints is correct, Python doesn't really do anything with them at runtime to improve performance, but rather the introspective use allows strictly third party applications such as linters, IDEs and static analysis tools (such as mypy
) to take advantage of their availability. So would those tools try to resolve the type hint of 'A'
rather than having that be a job given to the interpreter and if so, how do they accomplish this?
By using the typing
module, user code can perform the following:
>>> 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'>}
However, my question is aimed at whether or not Python has any responsibility in updating the __annotations__
of a function from a string literal, that is to say at runtime change:
>>> A().test.__annotations__
{'a': 'A', 'return': None}
to...
>>> A().test.__annotations__
{'a': <class '__main__.A'>, 'return': None}
If Python doesn't do it, then why would I want a string literal as a type hint other than for self-documented code? What value does the first form give to me, a user or a third party tool?