Understanding closures in Python: getting started with closures

Walker AI 2021-01-20 20:30:15
understanding closures python getting started

This article was first published in : Walker AI

python What is a closure in ? What's the use of closures ? Why use closures ? Today we'll take this 3 One problem is to know closures step by step .

Closures and functions are closely related , It's necessary to introduce some background knowledge before introducing closures , Such as nested functions 、 The scope of variables and so on .

1. Scope

Scope is the range of variables that can be accessed at runtime , Variables defined in a function are local variables , The scope of action of local variables can only be within the internal scope of the function , It cannot be referenced outside a function .

The variables defined in the outermost layer of the module are global variables , It's globally visible , Of course, you can also read global variables in functions . You can't access local variables outside the function . for example :

a = 1
def foo():
print(a) # 1 
 Copy code 
def foo():
print(a) # NameError: name 'num' is not defined 
 Copy code 

2. Nested function

Functions can be defined not only in the outermost layer of a module , It can also be defined inside another function , Functions defined in functions like this are called nested functions (nested function). For nested functions , It has access to nonlocals declared in its outer scope (non-local) Variable , For example, variables in the code example a Can be nested functions printer Normal visit .

def foo():
#foo It's a peripheral function 
a = 1
# printer It's a nested function 
def printer():
foo() # 1
 Copy code 

So is there a possibility that even if it is out of the scope of the function itself , Local variables can also be accessed ?

The answer is closures !

We change the above functions into higher order functions ( Accept a function as an argument , Or the function returned as a result is a higher-order function ) Writing .

def foo():
#foo It's a peripheral function 
a = 1
# printer It's a nested function 
def printer():
return printer
x = foo()
x() # 1
 Copy code 

This code has exactly the same effect as the previous example , The same output 1. The difference is in the internal function printer Directly returned as a return value .

In general , Local variables in a function are only available during the execution of the function , once foo() After execution , We would think of variables as a Will no longer be available . However , Here we find foo After execution , Calling x When a The value of the variable is output normally , That's what closures do , Closures make it possible for local variables to be accessed outside the function .

3. Closure

People sometimes confuse closures with anonymous functions . There are historical reasons for that : Define the function inside the function Less common , Not until you start using anonymous functions . and , Closure problems occur only when nested functions are involved . therefore , Many people know these two concepts at the same time .

Actually , A closure is a function that extends its scope , It contains references in the function definition body 、 But not in the definition body Non global variables . It doesn't matter if the function is anonymous , The key is that it can access non global variables defined outside the definition body .

Generally speaking, closures , seeing the name of a thing one thinks of its function , It's a sealed package , It's wrapped in free variables , Just like property values defined in a class , The visible range of the free variable is accompanied by the package , Where can I access this package , Where can I access this free variable . Where is the package bound ? Add a print sentence to the above code :

 def foo():
# foo It's a peripheral function 
a = 1
# printer It's a nested function 
def printer():
return printer
x = foo()
print(x.__closure__[0].cell_contents) # 1 
 Copy code 

You can see that it's in the function object __closure__ Properties of the ,__closure__ Is a meta ancestor object function responsible for closure binding , Binding of free variables . The value of this property is usually None, If this function is a closure , So what it returns is a result of cell Tuple objects made up of objects .cell Object's cell_contents Attributes are free variables in closures . This explains why local variables are separated from functions , It can also be accessed outside the function , Because it's stored in the cell_contents It's in .

4. The benefits of closures

Closures avoid using global variables , Besides , Closures allow functions to be manipulated with certain data ( Environmental Science ) Connected . This is very similar to object-oriented programming , In face object programming , Object allows us to put some data ( Object properties ) Associated with one or more methods .

Generally speaking , When there is only one method in an object , Using closures is a better choice . Let's take an example of calculating the mean value , If there's one called avg Function of , Its function is to calculate the mean value of the increasing series of values ; for example , Throughout history The average closing price of a commodity . New prices are added every day , So the average takes into account all the prices so far , As shown below :

>>> avg(10) #10.0 
>>> avg(11) #10.5 
>>> avg(12) #11.0 
 Copy code 

In the past , We can design a class :

class Averager():
def __init__(self):
self.series = []
def __call__(self, new_value):
total = sum(self.series)
return total/len(self.series)
avg = Averager()
avg(10) #10.0
avg(11) #10.5
avg(12) #11.0
 Copy code 

In this case, we use closures to implement .

def make_averager():
series = []
def averager(new_value):
total = sum(series)
return total/len(series)
return averager
avg = make_averager()
avg(10) #10.0
avg(11) #10.5
avg(12) #11.0
 Copy code 

call make_averager when , Return to one averager Function object . Every time you call averager when , It adds parameters to the list , Then calculate the current average . This is more elegant than using classes to implement , In addition, decorators are also an application scenario based on closures .

5. The pit of closure

After reading the above explanation of closures, you think closures are nothing more than that ? In actual use, we often fall into the trap inadvertently , Take a look at the following example :

def create_multipliers():
return [lambda x: x * i for i in range(5)]
for multiplier in create_multipliers():
# Expected output 0, 2, 4, 6, 8
# The result is 8, 8, 8, 8, 8
 Copy code 

We expect output 0, 2, 4, 6, 8. The result is 8, 8, 8, 8, 8. Why is this problem ? Let's change the code :

def create_multipliers():
multipliers = [lambda x: x * i for i in range(5)]
print([m.__closure__[0].cell_contents for m in multipliers])
create_multipliers() # [4, 4, 4, 4, 4] 
 Copy code 

You can see the function binding i It's all worth it 4 That is, after the cycle, finally i The value of , This is because Python The closure of is delayed binding , This means that the value of the variable used in the closure , It is obtained by querying when an internal function is called .

The right way to use it is to put i The value of is passed as a parameter :

def create_multipliers():
return [lambda x,i=i: x * i for i in range(5)]
s = create_multipliers()
for multiplier in s:
print(multiplier(2)) # 0, 2, 4, 6, 8
 Copy code 

We use default parameters to pass i, As with closures, the default parameter is bound to __defaults__ Attribute .

print([f.__defaults__ for f in s]) # [(0,), (1,), (2,), (3,), (4,)] 
 Copy code 

PS: More technical dry goods , Quick attention 【 official account | xingzhe_ai】, Discuss it with the traveler !

本文为[Walker AI]所创,转载请带上原文链接,感谢

  1. 利用Python爬虫获取招聘网站职位信息
  2. Using Python crawler to obtain job information of recruitment website
  3. Several highly rated Python libraries arrow, jsonpath, psutil and tenacity are recommended
  4. Python装饰器
  5. Python实现LDAP认证
  6. Python decorator
  7. Implementing LDAP authentication with Python
  8. Vscode configures Python development environment!
  9. In Python, how dare you say you can't log module? ️
  10. 我收藏的有关Python的电子书和资料
  11. python 中 lambda的一些tips
  12. python中字典的一些tips
  13. python 用生成器生成斐波那契数列
  14. python脚本转pyc踩了个坑。。。
  15. My collection of e-books and materials about Python
  16. Some tips of lambda in Python
  17. Some tips of dictionary in Python
  18. Using Python generator to generate Fibonacci sequence
  19. The conversion of Python script to PyC stepped on a pit...
  20. Python游戏开发,pygame模块,Python实现扫雷小游戏
  21. Python game development, pyGame module, python implementation of minesweeping games
  22. Python实用工具,email模块,Python实现邮件远程控制自己电脑
  23. Python utility, email module, python realizes mail remote control of its own computer
  24. 毫无头绪的自学Python,你可能连门槛都摸不到!【最佳学习路线】
  25. Python读取二进制文件代码方法解析
  26. Python字典的实现原理
  27. Without a clue, you may not even touch the threshold【 Best learning route]
  28. Parsing method of Python reading binary file code
  29. Implementation principle of Python dictionary
  30. You must know the function of pandas to parse JSON data - JSON_ normalize()
  31. Python实用案例,私人定制,Python自动化生成爱豆专属2021日历
  32. Python practical case, private customization, python automatic generation of Adu exclusive 2021 calendar
  33. 《Python实例》震惊了,用Python这么简单实现了聊天系统的脏话,广告检测
  34. "Python instance" was shocked and realized the dirty words and advertisement detection of the chat system in Python
  35. Convolutional neural network processing sequence for Python deep learning
  36. Python data structure and algorithm (1) -- enum type enum
  37. 超全大厂算法岗百问百答(推荐系统/机器学习/深度学习/C++/Spark/python)
  38. 【Python进阶】你真的明白NumPy中的ndarray吗?
  39. All questions and answers for algorithm posts of super large factories (recommended system / machine learning / deep learning / C + + / spark / Python)
  40. [advanced Python] do you really understand ndarray in numpy?
  41. 【Python进阶】Python进阶专栏栏主自述:不忘初心,砥砺前行
  42. [advanced Python] Python advanced column main readme: never forget the original intention and forge ahead
  43. python垃圾回收和缓存管理
  44. java调用Python程序
  45. java调用Python程序
  46. Python常用函数有哪些?Python基础入门课程
  47. Python garbage collection and cache management
  48. Java calling Python program
  49. Java calling Python program
  50. What functions are commonly used in Python? Introduction to Python Basics
  51. Python basic knowledge
  52. Anaconda5.2 安装 Python 库(MySQLdb)的方法
  53. Python实现对脑电数据情绪分析
  54. Anaconda 5.2 method of installing Python Library (mysqldb)
  55. Python implements emotion analysis of EEG data
  56. Master some advanced usage of Python in 30 seconds, which makes others envy it
  57. python爬取百度图片并对图片做一系列处理
  58. Python crawls Baidu pictures and does a series of processing on them
  59. python链接mysql数据库
  60. Python link MySQL database