Eraser, a new series of fun Internet advanced webworms, let’s Be More Pythonic together.

Closures

Closure, also known as closure function, closed function, written similar to function nesting.

8.1 Basic operations of closures

To break away from the complexity, in Python, a closure is when you call a function X, and that function returns a function Y to you, and that function Y returns is a closure.

Before mastering any technique, take a look at the basic case code:

def func(parmas) :
    # Inner function
    def inner_func(p) :
        print(F "external function argument{parmas}, internal function parameters{p}")

    return inner_func


inner = func("Outside")
inner("Within")
Copy the code

A call to func(” outer “) generates a closure inner_func that calls parmas, the parameter of func, which is called as a free variable. When func’s declaration cycle is over, the variable parmas is still there because it is called by inner_func, so it is not recycled.

After a brief introduction to closure manipulation, you will see that closure manipulation, which was used in the last blog post, is described as decorator.

The code above is commented again to help you understand the implementation of closure functions.

# Define the outer (outer) function
def func(parmas) :
    # Define inner (inner) functions
    def inner_func(p) :
        print(F "external function argument{parmas}, internal function parameters{p}")
	Be sure to return the inner function
    return inner_func

Inner is the inner function, and the free variable params is preserved
inner = func("Outside")
inner("Within")
Copy the code

To sum up, implementing a closure requires the following steps:

  1. There must be an inner function;
  2. The inner function must use the variables of the outer function. If you do not use the variables of the outer function, the closure is meaningless.
  3. The return value of the outer function must be the inner function.

8.2 Closure scope

First look at the code:


def outer_func() :
    my_list = []

    def inner_func(x) :
        my_list.append(len(my_list)+1)
        print(f"{x}-my_list:{my_list}")

    return inner_func


test1 = outer_func()
test1("i1")
test1("i1")
test1("i1")
test1("i1")

test2 = outer_func()
test2("i2")
test2("i2")
test2("i2")
test2("i2")
Copy the code

The scope of the free variable my_list in the above code is only dependent on the variables generated each time the outer function is called. The variables referenced by each instance of the closure do not interfere with each other.

8.3 The role of closures

Again, did you get a sense of what closures can do? Again, there are scope-related issues involved in closure operations, and the ultimate goal is that local variables can be accessed outside the scope of the function itself.

def outer_func() :

    msg = "Dream Eraser"
    def inner_func() :
        print(msg)

    return inner_func

outer = outer_func()
outer()
Copy the code

If you remember the first snowball run, you’ll notice that the MSG variable is only available during the execution of the function, so the MSG variable is not available after the outer_func function has been executed, but the MSG variable is also output when outer is called. This is where closures come in. Closures allow local variables to be accessed outside of functions. The corresponding theory is extended to say that in this case local variables can be used as global variables.

A closure holds some non-global variables, that is, local information that is not destroyed.

8.4 Determine closure functions

Determine if a function is a closure by its name.__closure__.

def outer_func() :

    msg = "Dream Eraser"
    def inner_func() :
        print(msg)

    return inner_func

outer = outer_func()
outer()
print(outer.__closure__)
Copy the code
(<cell at 0x0000000002806D68: str object at 0x0000000001D46718>,)
Copy the code

The first element of the tuple returned is the CELL, which is the closure function.

8.5 Problems with closures

This problem is the address and value of the problem is caused by the underlying principle of the operating system, the specific implementation of the first look at the code, a very classic case.

def count() :
    fs = []
    for i in range(1.4) :def f() :
            return i
        fs.append(f)
    return fs

f1, f2, f3 = count()
print(f1())
print(f2())
print(f3())
Copy the code

The above code does not simply return a closure. It returns a list of three closures. Run the code, print three 3’s, and if you’ve learned about references and values, the I in the code above refers to an address, not a value, so that when the loop ends, the value of I to that address is equal to 3.

You can also remember the following sentence in this case.

Try to avoid referencing loop variables in closures, or variables that will change later.

8.6 Summary of this blog

This blog has provided you with the basics of closures, as well as with the previous decorator blog.

Blogger ID: Dream eraser, hope you like, comment, favorites.