This is the 18th day of my participation in the August Genwen Challenge.More challenges in August

What is a closure

Closures are blocks of code that can contain free (unbound to a specific object) variables; These variables are not defined within the code block or in any global context, but in the context in which the code block is defined (local variables). The term “closure” comes from a combination of the code block to execute (free variables and the objects they reference are not released because they are contained in the code block) and the computational environment that provides bindings for free variables (scope). — Baidu Baike

We all know that programs have domains, from top-level namespaces to Java /C++ domain delimitors. Programs are blocks of code, either nested or stacked in parallel. Fields limit the scope of variables: each variable has its own scope (indentation of Python siblings and children, inside Java’s {}), and you cannot use variables outside the scope. The existence of closures, however, breaks this limitation in a way that makes the program look like variables are being accessed out of scope.

It looks like it, because it does. Closures in Python are typically implemented by a function that returns an embedded function. The nested function refers to a variable of an external function. When the nested function is returned by an external function, Python uses the “LEGB rule “to make the nested code block and its runtime environment (the variable of the referenced external function, But at this point, the functions that execute the wrapped object are already parallel, separate domains, and theoretically inaccessible) as if bundled together to return a wrapped object (everything is an object in Python). That is, closures seal the context in which functions are executed. A simple code illustration illustrates the process below.

What are closures good for

Closures allow nested functions of a function to be called directly outside the function. There is no need to deliberately use closures to stay in shape. The main purpose of closures is to ensure that local variables that a function may depend on (the runtime environment) are passed along with the function body when it is passed, ensuring that the function still runs correctly!

How do I write closure

This is a simple closure:

def outer() :
    out_ref = 'i am outer'
    def inner() :
        print(out_ref)
    return inner

f = outer()
f() 
# output: I am outer
Copy the code

In the program we can see:

  • Outer () returns the reference to inner, which refers to the inner function object.
  • I am outer f() == inner(

Here’s the problem: inner refers to the out_ref variable in outer. The scope of out_ref is inside outer (the green block below), so it’s fine to use out_ref inside outer. But the inner() call is f(), and f() is level with outer, so it makes sense that f() cannot access the out_ref variable because the block of f() is outside the scope of out_ref. F (), however, uses the out_ref variable correctly, which is a sign of the closure nature: it hides the context in which the inner function is returned! That is, when outer() returns inner, it returns out_ref and the function body object as if tied together, allowing us to still use variables out of scope.

Closure implementation mechanism

Since Python doesn’t really have an object that binds the body of a function to its runtime context, it does so through LEGB.

LEGB

The LEGB rule specifies how Python should query the location of a referenced variable when it encounters it. LEGB Description

  • L – Local (function); Namespaces inside functions (inner)
  • E – Enclosing function locals; Namespace of external nested functions (in outer)
  • G – Global (module); The namespace of the module (file) in which the function is defined
  • B – Builtin (Python); The namespace of Python’s built-in modules

The search is performed in L->E->G->B order, and the search is stopped as soon as a matching variable is found. If it is not found at all, NameError is raised. This is the LEGB rule.

Conditions for nested function closures

  1. There are nested functions (outer nested inner)
  2. Inner functions refer to outer function variables (inner references out_ref)
  3. An inner function is called in the same space as the outer function.

Then the variables of the outer function and the inner function will be the same closure!

Always note the errors caused by closures: F is a reference to a function. F does not execute a function in a reference. It holds the state of the reference to out_ref. F () is the execution of the function, which evaluates the result directly using the out_ref variable.