Closure function _python_ Scripting home in python

Closure functions in python

Updated: Feb 09, 2018 08:40:24 by renpingsheng
This article mainly introduces the closure function in python, very good, with reference value, need friends can refer to the next

A preliminary study of closure functions

This is how we usually define functions

def foo():
 pass

In fact, in functional programming, functions can also be nested inside functions, such as the following

def foo():
 print("hello world in foo")
 
 def bar():
 print("hello world in bar")

At this point we call the foo function, what will the result look like?

hello world in foo

As shown above, only the first layer of the foo function is executed, and the bar function is not executed. Why is that?

In fact, no matter where the function is written, it just defines a function, and only when the function is called, the statements inside the function will be executed

In the above example, the bar function is defined inside the foo function, but it is not executed, so the bar function is not executed. In this case, the function defined inside a function has no effect? That's not true.

Take a look at the following example, which returns the bar function as a value to the foo function to see the execution

def foo():
 print("hello world in foo")
 
 def bar():
 print("hello world in bar")
 return bar
f1=foo()
print(f1)

At this point, since the bar function is returned to foo as a return value, the result of the foo function is returned

At this point, define a variable f1 to receive the result of the execution of the foo function, and then print f1

The result returned is as follows

hello world in foo
<function foo.<locals>.bar at 0x0000000002941A60>

You can see that a print statement defined in the foo function is printed first, followed by the memory address of the bar function contained in the foo function

Since it is the memory address of a function, it is possible to execute the function with parentheses

def foo():
 print("hello world in foo")
 def bar():
 print("hello world in bar")
 return bar
f1=foo()
f1()

At this point, the result of this code execution is:

hello world in foo
hello world in bar

Both print statements are printed.

In the above example, we first define a function foo, then we nested a function bar inside the function foo, and then return the function name of the function bar, which is how the closure function is defined.

In fact, the definition of a closure is a function nested inside a function

Take a look at the following code

 def foo():
 print("hello world in foo")
 name="python"
 def bar():
  print(name)
  print("hello world in bar")
 return bar
 
 f1=foo()
 f1()

In the above example, a variable name is defined in the outer function, and the variable name is printed in the inner function

At this time, when executing the above code, when printing the name variable, it will first look up the name variable inside the bar function, but there is no name variable in the bar function.

At this time, according to python's LEGB law for finding variables, it will go to the outside layer of the bar function to continue to find the name variable, and at this time, it can find the name variable

So here we print the value of name defined in the foo function

Execute the above code and print the following result

hello world in foo
python
hello world in bar

The important thing to remember here is:

The inner function refers to the local variable of the outer function

Let's analyze the execution of the program in the above example:

At this time, the result of the execution of the foo function is defined to the variable f1, so f1 is equal to the memory address of the bar function, and then f1 is run with parentheses to indicate that the bar function is run. During the execution of the bar function, the bar function accesses the variables defined in the outer function foo. This is a typical closure function. What is the benefit of using a closure function? In the above example, the value of f1 is the memory address of the bar function, and running f1 in parentheses is running the bar function.

Since f1 is a global variable, this means that the f1 function can be run anywhere in the entire program, and then define a function, and call the f1 function inside this function.

 def foo():
 print("hello world in foo")
 name = "python"
 
 def bar():
  print(name)
  print("hello world in bar")
 return bar
 
 f1 = foo()
 
 def func():
 name = "aaaaa"
 f1()
 func()

Let's analyze the execution process of the program:

1. Run the func function, the program will first apply a space in memory to store the value of the name variable, and then run the f1 function, f1 is a variable defined in the global, so it must be able to find the memory address of the f1 function

2. When f1 runs with parentheses, it executes a closure function that internally references the name variable

3. The name variable has been defined outside the bar function, so when the f1 function, that is, the bar function, is called inside the func function, the variable it refers to is still the name variable defined inside the foo function, instead of the name variable defined inside the func function.

4. Because the f1 function already contains the value of the name function, even if the name variable is defined inside the func function, the result of the program execution is still the value of the name defined inside the foo function

Result of program execution

hello world in foo
python
hello world in bar

How do you verify that a function is a closure function

First, closure functions have a unique property: closure

In the example above, print the __closure__ attribute of f1

 def foo():
 name = "python"
 def bar():
  print(name)
  print("hello world in bar")
 return bar
 f1 = foo()
 print(f1.__closure__)

Print results are as follows:

(<cell at 0x0000000001DF5708: str object at 0x0000000001E79688>,)

You can see that the print result of the __closure__ attribute is a tuple whose value is the outer scope of the f1 function

The value of the name variable can then be printed by calling the cell_contents method of the element of the tuple returned by __closure__

 def foo():
 name = "python"
 
 def bar():
  print(name)
  print("hello world in bar")
 return bar
 
 f1 = foo()
 print(f1.__closure__[0].cell_contents)

Print results are as follows:

python

You can see that the program has printed out the value of the name variable

If __closure__ returns a tuple, then this tuple must contain multiple values, see the following example

Define multiple variables inside the foo function, and then print the values of several variables inside the bar function,

Then run the closure function, printing the closure function's __closure__ method

 def foo():
 print("hello world in foo")
 name1 = "python1"
 name2 = "python2"
 name3 = "python3"
 name4 = "python4" 
 def bar():
  print(name1)
  print(name2)
  print(name3)
  print(name4)
  print("hello world in bar")
 return bar 
 f1 = foo()
 print(f1.__closure__)

Result of program execution

(<cell at 0x0000000002145708: str object at 0x00000000021C9260>, 
<cell at 0x0000000002145A08: str object at 0x00000000021C93B0>, 
<cell at 0x0000000002145768: str object at 0x000000000295BE30>, 
<cell at 0x0000000002145C18: str object at 0x0000000002963880>)

Since four variables are defined inside the foo function and referenced inside the bar function, printing the closure function's __closure__ method returns a tuple with four elements

You can now print the values of each of the four string objects in the returned tuple separately

 def foo():
 name1 = "python1"
 name2 = "python2"
 name3 = "python3"
 name4 = "python4"
 
 def bar():
  print(name1)
  print(name2)
  print(name3)
  print(name4)
  print("hello world in bar")
 return bar 
 f1 = foo()
 print(f1.__closure__[0].cell_contents)
 print(f1.__closure__[1].cell_contents)
 print(f1.__closure__[2].cell_contents)
 print(f1.__closure__[3].cell_contents)

Result of program execution

python1
python2
python3
python4

So now there is one last question left, that is, must the inner function of the closure function return?

Consider the following example

 def foo():
 name = "python1" 
 def bar():
  print(name)
 print(bar.__closure__) 
 foo()

A nested function is defined, and instead of returning the inner function of the nested function, the inner function's __closure__ method is printed and the outer function is called directly.

Result of program execution

(<cell at 0x0000000002155708: str object at 0x00000000021D9688>,)

Still prints out the variable object referenced by the inner function

This means that the inner function of the closure function must also return

Can an inner function of a closure function call a global variable?

Change the variable defined inside the outer function to a global variable, and then reference the variable in the inner function

 name = "python1"
 def foo():
 def bar():
  print(name) 
 print(bar.__closure__)
 f=foo()
 print(f)

Result of program execution

None
None

As you can see, the result of the execution of the program is two NOnes, and the __closure__ function of the inner function of the nested function has the value None

This means that the global variable called by the inner nested function bar of the foo function did not succeed, so the above example is not a closure function

Some summary of closure functions:

A closure is defined as:

A function defined inside a function is called an inner function. An inner function calls a local variable of an outer function. Local variables can still be used even if the inner function returns. Usually the inner function of a closure function is returned to the outer function

What closure functions do

1. Closure functions have their own function scope

Enclose enclose a normal function that looks outward layer by layer, conforming to the LEGB(Local-> >Global->Built in) law,

But for a closure function, finding a variable will only look for the layer outside the inner function, because the closure function itself has a layer of scope, which is the meaning of the word "closure"

2. Delayed computing (also known as lazy computing)

Take a look at the following example

 def func():
 name="python"
 def bar():
  print(name)
 return bar 
 f=func()
 print(f.__closure)

In the example above, the return result of executing foo() is a function that contains its own state, which is not actually executed.

In the future, when you want to execute this function with its own state, you can execute it by parenthesis the variable assigned by the func() return result.

3. To keep a function in a state, you can use closures

Example:

 name="python" 
 def func():
 print("I like %s" % name) 
 func()

The result of the above code execution will print a line :"I like python"

However, we know that the printing result of the func function is very likely to be different in different places

So if I want to call func anywhere and the result is "I like python",

You can use closures.

 def func1(): 
 name="python"
 def func():
  print("I like %s" % name)
 return func
 func=func1()
 func()

As shown in the figure above, a second layer of function, func1, is included outside the func function, the func1 function is executed, and the result of the func1 function is assigned to the func variable

Now func is a closure function, and the func function can be executed with parentheses

And we must know that the result of the func function will print the words "I like python", and the result will be the same no matter where the func function is called in the program

Related article

  • python数据解析BeautifulSoup爬取三国演义章节示例

    python data parsing BeautifulSoup crawl Three Kingdoms chapter example

    This article mainly introduces the python data parsing BeautifulSoup chapter example, the article contains detailed example code, friends in need can use for reference, I hope to be helpful
    2021-09-09
  • Python如何破解压缩包密码

    How does Python crack the zip code

    Crack rar and zip compression packages. Windows under the use of PyCharm software, this article gives you a detailed introduction to Python how to crack the compression package password, interested friends take a look
    2022-05-05
  • Python+OpenCV实现图片中的圆形检测

    Python+OpenCV implements circle detection in images

    This article mainly introduces how to use Python+OpenCV to detect the circle in the picture, the example code in the article explains in detail, interested partners quickly follow the small series together to learn
    2022-04-04
  • Python自定义logger模块的实例代码

    Python custom logger module instance code

    The logging module in the Python standard library provides logging functions to customize the Logger Log recording can be customized according to the needs of the project to meet the specific log recording format, output target and log level requirements, this paper introduces the Python custom logger module instance code, need friends can refer to it
    2024-02-02
  • Python shelve模块实现解析

    The Python shelve module implements parsing

    This article mainly introduces the implementation of Python shelve module parsing, the article through the example code is very detailed, for everyone's study or work has a certain reference learning value, need friends can refer to it
    2019-08-08
  • Python3分析处理声音数据的例子

    Example of Python3 parsing and processing sound data

    Today, Xiaobian will share an example of Python3 analysis and processing of sound data for you, which has a good reference value, and I hope to help you. Let's take a look
    2019-08-08
  • 在Python中通过getattr获取对象引用的方法

    getattr method to get an object reference in Python

    Today, Xiaobian will share a method for getting object references through getattr in Python, which has a good reference value, and I hope to help you. Let's take a look
    2019-01-01
  • Python 装饰器代码解析

    Python decorator code parsing

    Decorators are an important part of Python. Simply put: they are functions that modify the functionality of other functions. They help make our code shorter and more Pythonic. Most beginners don't know where to use them, so I'm going to share a few examples
    2021-11-11
  • Python识别处理照片中的条形码

    Python recognizes barcodes in processed photos

    This article mainly introduces Python identification and processing of barcode in photos, to help you better use python to process pictures, improve office efficiency, interested friends can understand
    2020-11-11
  • 解决Python plt.savefig 保存图片时一片空白的问题

    Fixed an issue where Python plt.savefig saved images with blank space

    Today, Xiaobian will share a solution to the problem of Python plt.savefig saving a blank picture, which has a good reference value, and I hope to help you. Let's take a look
    2019-01-01

Latest comments