I was writing something that could be summarized as this:
def f(): some_variable = "Value" def inner_function(): some_variable = "New Value" inner_function() return some_variable print(f())
The output I was hoping for, as you may have guessed, was
New Value. Unfortunately, as I hadn't written anything particularly complicated in Python for a while at that point, I was stumped to find that the program consistently printed out
After a bunch of testing and a bit of head-scratching, I finally saw the problem: there needs to be a
nonlocal statement inside
def f(): some_variable = "Value" def inner_function(): nonlocal some_variable some_variable = "New Value" inner_function() return some_variable print(f())
Now the program does what I expected it to.
In theory, I knew that I needed the
Which brings us to the main points of this post. The first, of course, is to remind Python programmers to be careful of quirks like this in Python scope, especially since they tend to surface only in contexts that occur with fairly low frequency, reducing the chances of the programmer developing good reflexes for them when they are just starting to learn the language.
The other point, however, is that programming language designers should really think long and hard about how to make scope, shadowing, and variable declaration as intuitive as possible for the user. Unmarked shadowing can be confusing enough; including unmarked shadowing in addition to unmarked variable declaration is just asking for painful bugs.