[Python-Dev] PEP 572 semantics (original) (raw)

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 "", 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