What is the utility of a type annotation when the thing it refers to cannot exist?
Deferred annotation lookups are intended to be something that analysis time can make sense of but can always have no useful meaning at runtime. No nesting required: ``` from __future__ import annotations Class X: ... def foo(hi: X): ... del X ``` Now try analyzing foo at runtime... I assume "Boom" with that NameError again? (*On a phone, can't try it now)* I believe this isn't a problem get_type_hints() can ever solve. Code that does this isn't what I'd call "reasonably" structured for use with type hints. If anything, type checkers should try to warn about it? -gps On Tue, Dec 8, 2020, 7:03 PM Paul Bryan <pbr...@anode.ca> wrote: > Let's try an example that static type checkers should have no problem with: > > Python 3.9.0 (default, Oct 7 2020, 23:09:01) > > [GCC 10.2.0] on linux > > Type "help", "copyright", "credits" or "license" for more information. > > >>> from __future__ import annotations > > >>> > > >>> def make_a_class(): > > ... class A: > > ... def get_b(self) -> B: > > ... return B() > > ... class B: > > ... def get_a(self) -> A: > > ... return A() > > ... return A > > ... > > >>> A = make_a_class() > > >>> a = A() > > >>> > > >>> import typing > > >>> typing.get_type_hints(a.get_b) > > Traceback (most recent call last): > > File "<stdin>", line 1, in <module> > > File "/usr/lib/python3.9/typing.py", line 1386, in get_type_hints > > value = _eval_type(value, globalns, localns) > > File "/usr/lib/python3.9/typing.py", line 254, in _eval_type > > return t._evaluate(globalns, localns, recursive_guard) > > File "/usr/lib/python3.9/typing.py", line 493, in _evaluate > > eval(self.__forward_code__, globalns, localns), > > File "<string>", line 1, in <module> > > NameError: name 'B' is not defined > > >>> > > > > > On Tue, 2020-12-08 at 18:48 -0800, Guido van Rossum wrote: > > Yeah, static type checkers won't like it regardless. > > On Tue, Dec 8, 2020 at 6:39 PM Paul Bryan <pbr...@anode.ca> wrote: > > It appears that when from future import __annotations__, a type hint > annotation derived from a closure loses scope. > > Simplistic example: > > Python 3.9.0 (default, Oct 7 2020, 23:09:01) > > [GCC 10.2.0] on linux > > Type "help", "copyright", "credits" or "license" for more information. > > >>> def make_a_class(data_type): > > ... class Foo: > > ... def put_data(self, data: data_type): > > ... self.data = data > > ... return Foo > > ... > > >>> import typing > > >>> foo = make_a_class(str)() > > >>> typing.get_type_hints(foo.put_data) > > {'data': <class 'str'>} > > >>> > > > If I add a single import to the top, it breaks: > > Python 3.9.0 (default, Oct 7 2020, 23:09:01) > > [GCC 10.2.0] on linux > > Type "help", "copyright", "credits" or "license" for more information. > > *>>> from __future__ import annotations # added this line* > > >>> def make_a_class(data_type): > > ... class Foo: > > ... def put_data(self, data: data_type): > > ... self.data = data > > ... return Foo > > ... > > >>> import typing > > >>> foo = make_a_class(str)() > > >>> typing.get_type_hints(foo.put_data) > > Traceback (most recent call last): > > File "<stdin>", line 1, in <module> > > File "/usr/lib/python3.9/typing.py", line 1386, in get_type_hints > > value = _eval_type(value, globalns, localns) > > File "/usr/lib/python3.9/typing.py", line 254, in _eval_type > > return t._evaluate(globalns, localns, recursive_guard) > > File "/usr/lib/python3.9/typing.py", line 493, in _evaluate > > eval(self.__forward_code__, globalns, localns), > > File "<string>", line 1, in <module> > > NameError: name 'data_type' is not defined > > >>> > > > I don't see how I can supply the closure scope as localns to > get_type_hints. Any suggestions? Is constructing a > (dynamically-type-annotated) class in a function like this an anti-pattern? > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/5RK6VXF263F5I4CU7FUMOGOYN2UQG73Q/ > Code of Conduct: http://python.org/psf/codeofconduct/ > > > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/NRH4HBD36WDIP4WR2L4TLTOYMQL2NUFV/ > Code of Conduct: http://python.org/psf/codeofconduct/ > > > _______________________________________________ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/6P5GFROAVAYXU3DTELZRHHRCDRYUEWCG/ > Code of Conduct: http://python.org/psf/codeofconduct/ >
_______________________________________________ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/VX2LCY436LC4VTMGFXMEVK5UQHZSQQNC/ Code of Conduct: http://python.org/psf/codeofconduct/