[Python-Dev] PEP 572 semantics

Nick Coghlan ncoghlan at gmail.com
Thu Jul 5 18:32:40 EDT 2018


On Thu., 5 Jul. 2018, 10:23 am Steve Dower, <steve.dower at python.org> wrote:

> On 04Jul2018 1518, Tim Peters wrote:
> > The only new thing is specifying the scope of `a`, where "local to f"
> > means exactly the same thing as for any other name local to a function
> > today.  So far as the PEP semantics go, it doesn't even matter whether
> > an implementation _does_ implement some form of closure as such.  It
> > just has to provide the visible semantics of _lexically_ nested scopes
> > with indefinite extent, by whatever means it likes best.  That's what
> > "local to f" means (and has meant all along - well, since lexically
> > nested scopes were first introduced).
>
> In that case, please provide more examples of how it should work when
> the assignment expression appears to define a variable in a scope that
> is not on the call stack.
>
> Whether intentional or not, there will be changes to how and when names
> are resolved. The specification should provide enough information to
> determine the preferred behaviour, so we can tell the difference between
> intention changes and implementation bugs.
>
> For example, what should be returned from this function?
>
> >>> A = 0
> >>> def f(x):
> ...     if x:
> ...         [A := i for i in [1]]
> ...     return A
>
> As far as I can tell, the closest current equivalent will not compile:
>
> >>> A = 0
> >>> def f(x):
> ...     if x:
> ...         def g():
> ...             nonlocal A
> ...             A = 1
> ...         g()
> ...     return A
> ...
>   File "<stdin>", line 4
> SyntaxError: no binding for nonlocal 'A' found
>
> Is this the equivalent behaviour you want? Or do you want an
> UnboundLocalError when calling f(0)? Or do you want the global A to be
> returned? How should we approach decision making about these cases as we
> implement this? The PEP does not provide enough information for me to
> choose the right behaviour here, and I argue that it should.
>

Guido did fully specify this in his post on "__parentlocal" scoping, in
response to my request that this be clearly spelled out in the PEP (that
specification just hasn't been rolled back into the PEP yet).

While Tim's correct that the underlying runtime semantics here aren't new
(which is why PEP 558 doesn't need to change), there's a new requirement
imposed on a Python compiler's symbol table analysis pass to see "A :=
expr" in a comprehension or generator expression scope and interpret that
as equivalent to either:

1. An implied "global A" in the child scope if the parent scope is the
module scope, or A is explicitly declared as global in the parent scope

2. An implied "nonlocal A" in the child scope if the parent scope is a
function scope and A is not defined as global in that scope. If A is not
already declared as local or nonlocal in the parent scope, then it is
implicitly declared as local in that scope with no associated annotation
(akin to "if 0: for A in (): pass")

3. A compile time error if the parent scope is a class scope (since we
don't have any existing scope declaration semantics that can be used to
make that case work sensibly)

I'm still wondering if it might make sense to define a new
"TargetScopeError" subclass of SyntaxError for that last case, since it
isn't the assignment expression syntax itself that's the problem: it's
where that expression is located.

Cheers,
Nick.


> Cheers,
> Steve
> _______________________________________________
> 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/ncoghlan%40gmail.com
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/python-dev/attachments/20180706/ebc73ff4/attachment.html>


More information about the Python-Dev mailing list