Written in the book before

Before the formal speak “closure” the first thing we need to know “nested function” such a thing, I in the previous article based learning Python function object (zero) said, function not only can be passed as an object, can also be nested inside a function is a function, the nested function is what we want to do today.

Nested function

Let’s start with an example:

>>> def my_name():
...    def your_name():
...            print('your_name() is two dog')...print('my_name() is rocky')...Copy the code

Here is an example of a simple nested function. In the above code, your_name() is defined inside my_name(), and your_name() is called an “embedded function” of my_name() because it is defined inside my_name().

Then we call my_name() and get the following result:

>>> my_name()
my_name() is rocky
Copy the code

This result indicates that your_name() was not called at all, or that my_name() did not execute its code from top to bottom.

So what do I do if I want your_name() to be executed as well? In my_name(), call your_name().

>>> def my_name():
...    def your_name():
...            print('your_name() is two dog')... your_name()# Display calls to embedded functions.print('my_name() is rocky')...Copy the code

Let’s call my_name(). The result is as follows:

>>> my_name()
your_name() is two dog
my_name() is rocky
Copy the code

Now let’s think again. Can we call the embedded function your_name() separately from my_name()? Let’s try it:

>> your_name()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name 'your_name' is not defined
Copy the code

Your_name () is defined within my_name(), and its scope is limited to the body of my_name(). In this case, your_name() is defined within the body of my_name(). Your_name is bound by my_name() when using a variable.

Here’s another example:

>>> def fun1():
...    a = 1
...    def fun2():
...            a += 1
...            print('fun2 -- a = ',a)
...    fun2()
...    print('fun1 -- a = ',a)
...
Copy the code

Now, before we look at the results, what is the result of this function? After you think about it, look at the results below:

>>> fun1()
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
 File "<stdin>", line 6, in fun1
 File "<stdin>", line 4, in fun2
UnboundLocalError: local variable 'a' referenced before assignment
Copy the code

Did you guess right? The result is a run error! The reason for the error is that fun2() uses the variable a of fun1(). As an expression, the Python interpreter thinks the variable should be created in fun2() instead of referring to the variable in fun1().

In Python, we can use the keyword nonlocal as shown in the following example:

>>> def fun1():
...    a = 1
...    def fun2():
...   nonlocal a
...            a += 1
...            print('fun2 -- a = ',a)
...    fun2()
...    print('fun1 -- a = ',a)
...
Copy the code

We then call fun1() and get the following result:

fun2 -- a = 2
fun1 -- a = 2
Copy the code

So that’s the principle of nested functions, and all that’s left is to use it in practice to get a better understanding.

This nested function, in fact, can make dynamic function objects, and the topic goes on to be called “closures.”

closure

We all know the concept of closures in mathematics, but here I’m talking about closures in computer programming languages, which are widely used in functional programming.

The official definition of a closure is quite strict and difficult to understand, but I think it’s better explained in The Python Language and Its Applications — a closure is a function that can be dynamically generated by another function and can change and store the values of variables created outside the function. At first glance, this may seem rather difficult, but let me explain with a simple example:

>>> a = 1
>>> def fun():
...     print(a)
...
>>> fun()
1
>>> def fun1():
...     b = 1
...
>>> print(b)
Traceback (most recent call last):
 File "<stdin>", line 1, in <module>
NameError: name 'b' is not defined
Copy the code

Without a doubt, the first section of the program can run successfully, the variable defined by a = 1 can be called in the function, but conversely, the second section of the program has an error.

A = 1 can be used outside fun1(), but b = 1 can’t be used outside fun1(). It’s ok if we use scope relationships, but if we have to use variables outside of functions, we have to use variables inside of functions. What to do?

Let’s start with the following example:

>>> def fun():
...    a = 1
...    def fun1():
...            return a
...    return fun1
...
>>> f = fun()
>>> print(f())
1
Copy the code

If you have read the above article carefully, it will sound familiar to you, but this is essentially what we call nested functions.

In fun(), there are a = 1 and fun1(), both of which are in the context of fun(), but they don’t interfere with each other, so a is a free variable relative to fun1(), And we apply this free variable to the function fun1() — fun1() is the closure we define.

A closure is really just a function, but the function has to have

  • 1. Define in another function (nested function);
  • 2. Reference the free variable of the environment.

Print (f()) gets the result because a = 1 can still exist in f(), i.e. fun1(), when fun() is finished.

Closures are quite comfortable when there are times when we need a higher level of abstraction for transactions. For example, if we want to write a quadratic function with two variables, you can easily write it without using a closure. Let’s use the closure method to complete the quadratic equation with one variable:

>>> def fun(a,b,c):
...    def para(x):
...            return a*x**2 + b*x + c
...    return para
...
>>> f = fun(1,2,3)
>>> print(f(2))
11
Copy the code

The above function, f = fun (1, 2, 3) a yuan quadratic function defines a function object, x ^ 2 + 2 x + 3, if you want to calculate x = 2, the value of quadratic function, a yuan you just need to calculate f (2), it seems that this kind of writing is more concise?

When we go back and look at the application of closures later on when we’ve learned about classes, you’ll actually get a better idea, and we’ll talk about that later, but it’s good to know that there’s a class.

Written in the book after

Of course there are many other ways closures can be used in the real world, so I’m going to leave you there as a zero basis for this series, and maybe I’ll talk about it a little bit more later in another series, but if you’re interested in this right now, Google the articles on this, there are a lot of them.

For more content, please follow the public account “Python Space”, looking forward to communicating with you.