<div dir="ltr"><div class="gmail_quote"><div dir="ltr">[Steve Dower]</div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">In that case, please provide more examples of how it should work when<br>
the assignment expression appears to define a variable in a scope that<br>
is not on the call stack.<br></blockquote><div><br>Sorry, I'm not clear what you're asking about.  Python's scopes are determined statically, at compile-time - they have nothing directly to do with what's on the call stack at runtime.  This PEP doesn't change anything about that, either.<br><br><br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Whether intentional or not, there will be changes to how and when names<br>
are resolved.</blockquote><div><br>Assignment expressions don't currently exist, so it's not possible to change how their targets' names get resolved ;-)  If the resolution of any _other_ names got changed, that would be a bug, not an unintended consequence.<br><br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> The specification should provide enough information to<br>
determine the preferred behaviour, so we can tell the difference between<br>
intention changes and implementation bugs.<br>
<br>
For example, what should be returned from this function?<br></blockquote><div><br>Thanks!  This clearly requires examples to flesh it out.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
>>> A = 0<br>
>>> def f(x):<br>
...     if x:<br>
...         [A := i for i in [1]]<br>
...     return A<br>
<br></blockquote><div>It depends on how it's called.  `A` is local to `f` in any case (your global `A` is wholly irrelevant here)..  f(x) would raise UnboundLocalError if `x` is not truthy, and return 1 if `x` is truthy.</div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
As far as I can tell, the closest current equivalent will not compile:<br>
<br>
>>> A = 0<br>
>>> def f(x):<br>
...     if x:<br>
...         def g():<br>
...             nonlocal A<br>
...             A = 1<br>
...         g()<br>
...     return A<br>
...<br>
  File "<stdin>", line 4<br>
SyntaxError: no binding for nonlocal 'A' found<br></blockquote><div><br>That's because it's an incorrect translation:  the "if the name is otherwise unknown in the containing block, establish it as local in the containing block" requires code in a "by hand" translation to force that to be the case.  "Otherwise unknown" means "is not declared global or nonlocal in the block, and is not already known to be local to the block".</div><div><br>Because `A` isn't assigned to in the body of `f` outside the listcomp, CPython _today_ has no idea `A` is intended to be local to `f`, so a by-hand translation requires adding silly cruft to force `A` to be recognized as local to `f`.  Perhaps the easiest "covers all cases" way:<br><br><div>    def f(x):</div><div>        if 0:              # NEW CODE HERE</div><div>            A = None # AND HERE</div><div>        if x:</div><div>           # etc</div><div><br></div>That doesn't generate any code at all in CPython (the optimizer throws away the entire "if 0:" block)..  But compile-time analysis _does_ see the "A = None" binding before the code is thrown away, and that's enough to establish that `A` is local to `f`.  Then it compiles fine today, and:<br><br><div>>>> f(0)</div><div>Traceback (most recent call last):</div><div>    ....</div><div>    return A<br></div><div>UnboundLocalError: local variable 'A' referenced before assignment</div><div>>>> f(1)</div><div>1</div><div><br></div></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><br>
Is this the equivalent behaviour you want? </blockquote><div><br>No, `A` is local to `f` - no compile-time error is appropriate here.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Or do you want an<br>
UnboundLocalError when calling f(0)?</blockquote><div><br>Yup, because `A` is local to `f` but not bound at the time it's referenced.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> Or do you want the global A to be returned?</blockquote><div><br>If and only if there was a `global A` declaration in `f`.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"> How should we approach decision making about these cases as we<br>
implement this? The PEP does not provide enough information for me to<br>
choose the right behaviour here, and I argue that it should.<br><br></blockquote><div>Well, as before, the PEP pretty clearly (to me) already says that `A` is  local to `f`.  Everything else about the semantics follows from that.  But also as in an earlier reply, I think the PEP could help by providing some worked-out workalike-function examples.  The "if 0:" trick above isn't deep, but it is too "clever" to be obvious.  Then again, it's not required to _specify_ the semantics, only to illustrate one possible way of _implementing_ the semantics.<br><br></div></div></div>