[Python-Dev] Postponed annotations break inspection of dataclasses

Guido van Rossum guido at python.org
Sat Sep 22 12:41:22 EDT 2018

This is a good catch -- thanks for bringing it up. I'm adding Eric Smith
(author of dataclasses) and Ivan Levkivskyi (co-author of typing) as well
as Łukasz Langa (author of PEP 563) to the thread to see if they have
further insights.

Personally I don't think it's feasible to change PEP 563 to use lambdas (if
it were even advisable, which would be a long discussion), but I do think
we might be able to make small improvements to the dataclasses and/or
typing modules to make sure your use case works.

Probably a bugs.python.org issue is a better place to dive into the details
than python-dev.

Thanks again,

--Guido (top-poster in chief)

On Sat, Sep 22, 2018 at 8:32 AM David Hagen <david at drhagen.com> wrote:

> 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.
> _______________________________________________
> Python-Dev mailing list
> Python-Dev at python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org

--Guido van Rossum (python.org/~guido)
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180922/a66a20f7/attachment.html>

More information about the Python-Dev mailing list