SoFunction
Updated on 2024-12-19

About closures in Python in detail

1, the concept of closure

Please follow me to understand that if a function is defined inside another function, the outer one we call it an outer function and the inner one we call it an inner function. Closure: An outer function defines an inner function, the inner function utilizes the temporary variables of the outer function, and the return value of the outer function is a reference to the inner function. This constitutes a closure. Generally, in our knowledge, if a function ends, everything inside the function will be released, returned to memory, and local variables will disappear. But closure is a special case, if the outer function in the end of the function found that there are their own temporary variables will be used in the internal function in the future, so the temporary variables bound to the internal function, and then their own end.

2、Implement a closure

# Returning a function as a return value is also a higher-order function
# This kind of higher-order function is also called a closure, through which you can create variables that are accessible only to the current function.
# Closures that can hide some private data in them

def outer():
    a = 10

    # Define another function inside the function
    def inner():
        print('I'm an outer'., a)

    # Return the inner function inner as a return value
    return inner


# r is a function object that is returned from a call to fn()
# This function is defined inside fn(), not globally.
# So this function always has access to the variables inside the fn() function #
# The outer function returns a reference to the inner function
fn = outer()

# r() is equivalent to calling the inner() function
print("outer reference address:", outer)
print("inner citation address:", fn)
fn()
"""
Output result:
outer reference address: <function outer at 0x0000000002BB5948>;
inner reference address: <function outer.<locals>.inner at 0x0000000002BB58B8>
I am outer 10
"""

Describe the above code:

For closures, the outer functionouterIn the last return inner, we are calling the outer functionfn = outer() of the time.outerfunction returns theinnerfunction object.innerA function object is a reference to a function that is deposited into thefnin the object. So next we'll do thefn() is equivalent to running theinnerfunction.

Tip:

A function whose name is immediately followed by a pair of parentheses is equivalent to calling the function. If it's not followed by parentheses, it's just the name of a function with a reference to its location.

3, in the closure outside the function to bind temporary variables to the inner function

As we normally perceive it, a function ends by releasing all its temporary variables back into memory, after which none of the variables exist. In general, this is indeed the case. But closures are a special case. The outer function realizes that its own temporary variables will be used in future inner functions, and when it ends, it returns to the inner function while giving the outer function's temporary variables to the inner function to bind them together. So the outer function has ended, and the call to the inner function can still use the temporary variables of the outer function.

In the example I wrote, I called the external function twiceouter, respectively, passed in values of 10 and 20. the internal function is defined only once, and we find that the call is different when the internal function is able to recognize the temporary variables of the external function.

Everything in Python is an object, and although the function we defined only once, the outer function actually executes according to the inner code when it runs. A function is created in the outer function, and every time we call the outer function, it creates an inner function, which creates a different object even though the code is the same, and binds the value of the temporary variable passed in each time to the inner function, which then reference back.

So each time we call the outer function, it returns a reference to a different instance object, they have the same function, but they are not actually the same function object.

The following example demonstrates this:

def outer(num):
    a = num

    # Define another function inside the function
    def inner():
        print('I'm an outer.', a)

    # Return the inner function inner as a return value
    return inner


fn1 = outer(10)
fn2 = outer(20)


print("inner citation address:", fn1)
fn1()
print("inner citation address:", fn2)
fn2()
"""
Output result:
inner Referenced by: <function outer.<locals>.inner at 0x00000000026B58B8>;
I am outer 10
inner reference address: <function outer.<locals>.inner at 0x00000000026B5828>
I am outer 20
"""
# Watch out for twoinnerIt's not the same address.,one is8B8,one is828。

4, the closure within the function to modify the outer function local variables

In basic Python syntax, a function can read global data at will, but there are two ways to modify global data

globalDeclare global variables. Global variables can be modified when they are variable type data.

The situation is similar in the inner function of a closure. When you want to modify a closure variable (a local variable bound to the inner function by the outer function) in the inner function, in Python 3, you can use thenonlocalThe keyword declares a variable that is not in local variable space and needs to be found one level up in variable space.

Example:

def outer(num):
    a = num
    b = 10  # a and b are both closure variables
    print("The original a-value is ", a)

    # inner inner function
    def inner():
        # Inside functions that want to modify closure variables
        # The nonlocal keyword declares variables
        nonlocal a
        a += b
        print('I am the a of outer', a)

    # Return the inner function inner as a return value
    return inner


fn1 = outer(10)

fn1()
"""
Output results:
Original a value is 10
I am outer for a 20
"""

In the inner function, the closure variable is modified, and the printout is indeed the result of the modification.

5. Note:

One other thing to note is that there is actually only one copy of the closure variable, one closure variable called at a time. (This is explained more in the Python implementation of unary mode)

def outer(num):
    a = num
    b = 10  # a and b are both closure variables
    print("The original a-value is ", a)

    # inner inner function
    def inner():
        # Inside functions that want to modify closure variables
        # The nonlocal keyword declares variables
        nonlocal a
        a += b
        print('I am the a of outer.', a)

    # Return the inner function inner as a return value
    return inner


fn1 = outer(10)

fn1()
fn1()
fn1()
"""
Output results:
Original a value is 10
I am outer's a 20
I am outer's a 30
I am outer's a 40
"""

You can see that the second second callfn1()Methods.aThe value has increased by 10.

6. Exercise:

# Find the average of multiple numbers
# nums = [50,30,20,10,77]

# sum() is a summation function
# sum() is used to find the sum of all the elements in a list.
# print(sum(nums)/len(nums))
# Outcome: 37.4


# Elements of closure formation
# ① Nested Functions
# ② Returning internal functions as return values
# ③ Internal functions must use variables from external functions.


def make_averager():
    # Create a list to hold the values
    nums = []

    # Create a function to calculate the average
    def averager(n) :
        # Add n to the list
        (n)
        # Averaging
        return sum(nums)/len(nums)

    return averager

# Create the object, which is now getting a reference to the inner function object
averager = make_averager()

# Call the inner book object
# Note here that although the object was created by calling an external function.
# But what you get is a reference to the inner function object, which has a formal parameter.
# So the averager object is equivalent to the inner function object.
# So a call to an inner function passes a formal parameter.
print(averager(10))
print(averager(20))
print(averager(30))
print(averager(40))

summarize

to this article on the Python closure detailed article on this, more related to Python closure content, please search for my previous articles or continue to browse the following related articles I hope you will support me in the future more!