Search code examples
pythonscopegenerator

Variable in generator function shadows name from outer scope


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.


Solution

  • 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.