I recently started to teach myself Python and currently work on generator functions. Here, I encountered a "scoping" issue with variable names inside of the generator shadowing names in outer scope. I did some research on this but could not come up with an explanation.
Given this minimal example:
def do_stuff(var):
shadow = var * var
def dummy_generator(size):
for i in range(size):
do_stuff(i)
yield i
if __name__ == '__main__':
for shadow in dummy_generator(5):
print(shadow)
PyCharm emits the warning "Shadows name 'shadow' from outer scope" for 'shadow' in the do_stuff function (I'm using Python 3.10.9 on Linux).
I would like to understand why this is the case.
The if __name__ == '__main__':
guard is just an ordinary if
statement. If statements don't introduce a new scope, so the statements in its body are evaluated in the surrounding (global) scope. Hence the loop
for shadow in dummy_generator(5):
is assigning to the global variable shadow
.
When you then write shadow = var * var
inside do_stuff
, you're introducing a local variable shadow
that is shadowing the global variable shadow
. Any further uses of shadow
in do_stuff
would resolve to that local variable as opposed to the global variable. This could be indicative of a mistake in your code (maybe you thought you were accessing the global shadow
when really you're using the local variable), or at very least can be confusing to people reading your code, which is why PyCharm is emitting are warning for it.