Search code examples
pythonpython-3.xscopenested-function

Positional arguments in nested functions


This question relates to this video: https://www.youtube.com/watch?v=jXugs4B3lwU

The piece I'm missing is somewhat simpler than the concept the video is covering overall. In the example code below: Why does the inner function (inner()) pick up the value of the argument that is passed in function call of f and g? (i.e. f("y arg"), g("other y arg"))

To my untrained eye, the level_five function only has one parameter defined ('n') which is referenced in the variable assignment to 'z' under the level_five function definition. At no point is a parameter called 'y' defined in the outer (level_five) function definition to be passed to inner()....so how does inner() implicitly pick up the passed value as it's y parameter when the outer function is being called?

I feel like it's because when the function is assigned to f or g, the first positional argument has been defined (i.e. this value goes to parameter 'n' of level_five when f or g are called), and then the argument supplied to f or g when they are called, is somehow mysteriously picked up using as a second positional parameter as though there is an implicit *args in the level_five definition, and is thus making its way to inner()....I've managed to confuse myself on exactly how this is happening, can anyone clarify this?

x = "global x"    

def level_five(n):
    z = f"outer z {n}"

    def inner(y):
        return x, y, z

    return inner

def main():
    f = level_five(0)
    g =  level_five(1)
    print(f("y arg"), g("other y arg"))

main()

Solution

  • When you run the level_five(0), it returns a function and stores it in f. As the function has not run yet, there was no need to pass any argument (y) to the function (inner). The function stored in f behaves like:

    def f(y):
    
       return 0 , y , "outer z 0"
    

    and then you can simply run f as you did in the print statement.