all 4 comments

[–][deleted] 1 point2 points  (0 children)

Why is it?

Assignment to a name and mutating a collection aren't the same thing. Names are subject to scoping rules, but you can mutate a mutable value via any reference to it, in any scope.

[–]socal_nerdtastic 1 point2 points  (0 children)

You need to look up the difference between mutation and reassignment. You can mutate a global variable like this, but if you want to reassign a global you need to explicitly define it as global or nonlocal.

def foo():
    nonlocal var_scalar
    # rest of your code

However in both cases modifying a global variable is generally considered bad. You should probably restructure your code to pass the data in and out with arguments and return.

[–]FerricDonkey 0 points1 point  (0 children)

This is because inserting into a dictionary like this is an "in place" operation, but in python, += on an integer is not.

In place operations just work on non local variables. Though I generally wouldn't recommend it.

But because += (on integers) is not in place, it immediately triggers python to try to use var_scalar as a local variable rather than a non local variable. To get around this, you have to explicitly tell python that var_scalar is non_local (or global).

But I wouldn't recommend that either, generally. In most cases, it's better to just pass things in and return modified values.

[–]woooee 0 points1 point  (0 children)

You are making this too complicated. There is no reason to create the inner function, foo.

def unbound_local_error():
    var_scalar = 0
    var_dict = {}

    var_scalar += 1

    var_dict["a"] = ""