On Thu, May 28, 2020 at 12:11:38PM +0200, Alex Hall wrote:
Consider this code:
``` x = 1
def foo(): print(x) x = 2
foo() ```
Here `print(x)` doesn't print '1', it gives `UnboundLocalError: local variable 'x' referenced before assignment`. It knows that `x` is meant to be a local and ignores the global value. That doesn't look like an implementation detail to me - does Jython do something different?
I never said that Python's scoping rules were implementation details. I said that the storage mechanism of *how* local variables are stored, and hence whether or not writes to `locals()` are reflected in the local variables, is an implementation detail. I'm too lazy to look it up right now, but I'm 99.9999999% (nine nines) certain that Python's execution model defines that any binding operation inside the function scope to an undotted name inside a function must make it a local, unless explicitly declared nonlocal or global. (Even if that binding operation is unreachable code.) Binding operations include regular assignment with `=`, imports, `for`, `with ... as`, `except ... as`, and `del`. I don't know about the walrus operator. That means that any non-buggy compliant Python must print NameError, or its subclass UnboundLocalError, when calling your foo function above. (I *think* that NameError would be acceptable, but you might have to ask the Steering Council to make a ruling if it's not already documented.) However the behaviour of locals()['x'] = 999 inside that function is explicitly documented as subject to implementation differences, which is what I was talking about. For the record, both IronPython and Jython 2.7 raise UnboundLocalError, but micropython just raises NameError: $ micropython MicroPython v1.9.4 on 2019-01-13; linux version Use Ctrl-D to exit, Ctrl-E for paste mode
x = 1 def spam(): ... print(x) ... x = 2 ... spam() Traceback (most recent call last): File "<stdin>", line 1, in <module> File "<stdin>", line 2, in spam NameError: local variable referenced before assignment
Micropython often gets special dispensation to bend the rules, but in this case I don't think that it needs it. So long as any implementation raises a NameError, not necessarily UnboundLocalError, I think that's sufficient. -- Steven