Home > Blockchain >  How is this function passed an argument with no parameter?
How is this function passed an argument with no parameter?

Time:06-27

I'm currently learning about closure and this code was presented:

def outer_func(x):
    y = 4
    def inner_func(z):
        print(f"x = {x}, y = {y}, z = {z}")
        return x   y   z
    return inner_func

for i in range(3):
    closure = outer_func(i)
    print(f"closure({i 5}) = {closure(i 5)}")

I understand x is defined at the point outer_func is assigned to closure, and y is defined within the function each time. My question is how is z defined? Shouldn't the call to closure overwrite the value of x? How does python know to assign this new value to z?

CodePudding user response:

My question is how is z defined?

z is a parameter of inner_func. It means it's always local to the inner_func function(local variable). When the outer_func function is called the body of it will be executed, which indeed first create inner_func and give you back a reference to it. Then whatever you pass to inner_func, it uses as the z. It's a normal argument passing.

Shouldn't the call to closure overwrite the value of x?

inner_func is your closure. It has access to it's enclosing scope which is outer_func. x is a parameter of outer_func, it gets it's value from executing the line:

closure = outer_func(i)

So whatever you pass to outer_func becomes available to the inner_func's body. (Closure mechanism)

How does python know to assign this new value to z?

I already answered this in the first part. In the line:

print(f"closure({i 5}) = {closure(i 5)}")

you are passing the value of z in closure(i 5) part.


Q: Now where does inner_func get y's value from? A: Again it's a closure, it has access to outer_func namespace. y is always defined when outer_func() is called. Nothing can change it's value in your code. That loop can only change x because it comes from outside. (argument)

CodePudding user response:

Your question is:

I understand x is defined at the point outer_func is assigned to closure, and y is defined within the function each time. My question is how is z defined? Shouldn't the call to closure overwrite the value of x? How does python know to assign this new value to z?

Your code is:

def outer_func(x):
    y = 4
    def inner_func(z):
        print(f"x = {x}, y = {y}, z = {z}")
        return x   y   z
    return inner_func

for i in range(3):
    closure = outer_func(i)
    print(f"closure({i 5}) = {closure(i 5)}")

The call to closure is effectively a call to inner_func (not outer_func) and the argument passed to closure will be assigned to z (not x).

Explanation:

Each execution of closure = outer_func(i) does the following:

  • call outer_func() thereby effectively assigning the passed argument i to the variable x in the scope of outer_func()
  • execute y = 4
  • leave outer_func() with a return value of type function whose value is inner_func
  • assign the return value of outer_func() (namely the function inner_func) to closure, with ongoing access to the variables in the containing scope of inner_func() (namely, the scope of outer_func()).

Each call to closure() within the for loop does the following:

  • call inner_func() thereby assigning the passed argument to z in the scope of inner_func()
  • execute the body of inner_func() where x and y have the values they had at the time of the call to outer_func() that created this copy of inner_func as a closure.
  • Related