[Python-Dev] PEP 563: Postponed Evaluation of Annotations

Nick Coghlan ncoghlan at gmail.com
Sat Nov 4 09:51:41 EDT 2017


On 4 November 2017 at 00:40, Guido van Rossum <guido at python.org> wrote:
> IMO the inability of referencing class-level definitions from annotations on
> methods pretty much kills this idea.

If we decided we wanted to make it work, I think the key runtime
building block we would need is a new kind of cell reference: an
IndirectAttributeCell.

Those would present the same interface as a regular nonlocal cell (so
it could be stored in __closure__ just as regular cells are, and
accessed the same way when the function body is executed), but
internally it would hold two references:

- one to another cell object (__class__ for this use case)
- an attribute name on the target object that get/set/del operations
on the indirect cell's value should affect

As Python code:

    class IndirectAttributeCell:
        def __new__(cls, cell, attr):
            self._cell = cell
            self._attr = attr

        @property
        def cell_contents(self):
            return getattr(self._cell.cell_contents, self._attr)

        @cell_contents.setter
        def cell_contents(self, value):
            setattr(self._cell.cell_contents, self._attr, value)

        @cell_contents.deleter
        def cell_contents(self):
            delattr(self._cell.cell_contents, self._attr)

The class body wouldn't be able to evaluate the thunks (since
`__class__` wouldn't be set yet), but `__init_subclass__`
implementations could, as could class decorators.

It would require some adjustment in the compiler as well (in order to
pass the class level attribute definitions down to these implicitly
defined scopes as a new kind of accessible external namespace during
the symbol analysis pass, as well as to register the use of
"__class__" if one of the affected names was referenced), but I think
it would work at least at a technical level (by contrast, every other
idea I came up with back when I was working on the list comprehension
change was sufficiently flawed that it fell apart within a few hours
of starting to tinker with the idea).

As an added bonus, we could potentially also extend the same
permissive name resolution semantics to the implicit scopes used in
comprehensions, such that it was only the explicitly defined scopes
(i.e. lambda expressions, function definitions, and nested classes)
that lost implicit access to the class level variables.

Cheers,
Nick.

P.S. If we subsequently decided to elevate expression thunks to a
first class language primitive, they shouldn't need any further
semantic enhancements beyond that one, since the existing scoping
rules already give the desired behaviour at module and function scope.

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


More information about the Python-Dev mailing list