Message 326148 - Python tracker (original) (raw)
The new postponed annotations have an unexpected interaction with dataclasses. Namely, you cannot get the type hints of any of the data classes methods.
For example, I have some code that inspects the type parameters of a class's __init__
method. (The real use case is to provide a default serializer for the class, but that is not important here.)
from dataclasses import dataclass
from typing import get_type_hints
class Foo:
pass
@dataclass
class Bar:
foo: Foo
print(get_type_hints(Bar.__init__))
In Python 3.6 and 3.7, this does what is expected; it prints {'foo': <class '__main__.Foo'>, 'return': <class 'NoneType'>}
.
However, if in Python 3.7, I add from __future__ import annotations
, then this fails with an error:
NameError: name 'Foo' is not defined
I know why this is happening. The __init__
method is defined in the dataclasses
module which does not have the Foo
object in its environment, and the Foo
annotation is being passed to dataclass
and attached to __init__
as the string "Foo"
rather than as the original object Foo
, but get_type_hints
for the new annotations only does a name lookup in the module where __init__
is defined not where the annotation is defined.
I know that the use of lambdas to implement PEP 563 was rejected for performance reasons. I could be wrong, but I think this was motivated by variable annotations because the lambda would have to be constructed each time the function body ran. I was wondering if I could motivate storing the annotations as lambdas in class bodies and function signatures, in which the environment is already being captured and is code that usually only runs once.
Original mailing list discussion: https://mail.python.org/pipermail/python-dev/2018-September/155289.html