[Python-ideas] Delay evaluation of annotations

Nick Coghlan ncoghlan at gmail.com
Fri Sep 23 13:00:56 EDT 2016


On 24 September 2016 at 01:58, Chris Angelico <rosuav at gmail.com> wrote:
> Default arguments trip some people up because they expect them to be
> evaluated when the function's called, but it can easily be explained.
> Function annotations are exactly the same. Making them magically
> late-evaluate would have consequences for the grokkability of the
> language - they would be special. Now, that can be done

Folks have been assuming that's straightforward, but the way class
namespaces work actually makes it significantly harder than it first
appears. Using lambda and default arguments to illustrate the problem:

    >>> class Example:
    ...     attr = 10
    ...     @staticmethod
    ...     def good_method(eager=attr):
    ...         return eager
    ...     @staticmethod
    ...     def bad_method(lazy=(lambda:attr)):
    ...         return lazy()
    ...
    >>> Example().good_method()
    10
    >>> Example().bad_method()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 8, in bad_method
      File "<stdin>", line 7, in <lambda>
    NameError: name 'attr' is not defined

By design, function scopes can't see attributes defined in containing
class scopes, and we don't currently have any other kind of scope that
supports delayed evaluation (unlike function bodies, class bodies are
evaluated eagerly at class definition time, and all the other delayed
evaluation constructs are syntactic sugar for some particular flavour
of function scope definition - even generators and coroutines use the
same basic name resolution scheme as regular functions, they just use
different execution models).

If it was still 2006 or 2007 and Python 3.0 hadn't been released yet,
lazy annotations could seriously be considered as an option. It's 2016
though, eager annotations have been out in the wild since December
2008, and the existing "string literals are Python's de facto lazy
evaluation syntax" approach works well enough for the purpose, since
type checkers can say they're actually going to parse those string
literals when they appear to be type hints.

Cheers,
Nick.

-- 
Nick Coghlan   |   ncoghlan at gmail.com   |   Brisbane, Australia


More information about the Python-ideas mailing list