On Thu, May 28, 2020 at 11:57 AM Steven D'Aprano <steve@pearwood.info> wrote:
On Wed, May 27, 2020 at 05:03:09AM +1000, Chris Angelico wrote:

> def foo():
>     if False: x = 0
>     # what is x now?
>
> There is no *value* in x, yet x has a state.

In Python code, no, it has no state, it's just an unbound name. That's
literally a name that has nothing bound to it, hence no state.

In the CPython 3 implementation, it has a hidden state: there's a fixed
array representing the locals, one of those array slots represents x,
and there is some kind of C-level special state to distinguish between
"this slot is filled" and "this slot is not filled". But that's purely
an optimization. Locals can also be backed by a dict, like globals.

That is what happens in Jython, so when you call locals() you get back
the actual local namespace dict and modifications to the variables
works. (Unlike in CPython.)

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?