在这篇博文中,你将学到什么是Python closure,如何定义一个closure,以及判断为什么用这个技术。
1. Nonlocal variable in a nested function
我们在进入closure概念之前,先理解什么是nested函数和non-local变量。
定义在一个函数内部的函数的叫 nested function,能访问enclosing域的变量。
在Python中,这些non-local变量默认只能被读(are read only),如果要修改它们,必须显式地把它们声明为non-local(使用non-local keyword)。
nested函数访问non-local变量的例子:
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
printer()
# We execute the function
# Output: Hello
print_msg("Hello")
我们看到nested函数 printer( ) 能访问enclosing函数中的non-local变量 msg
2.Defining a Closure Function
在上面的例子中,要是函数 printer_msg( ) 最后一行换成 return printer 会出现什么情况?现在函数变化如下:
def print_msg(msg):
# This is the outer enclosing function
def printer():
# This is the nested function
print(msg)
return printer # this got changed
# Now let's try calling this function.
# Output: Hello
another = print_msg("Hello")
another()
是不是感觉结果很不寻常。
传入参数“hello”,调用 print_msg( ) 函数,返回的是一个函数名 another (注意没有带括号)。当调用 another( ) (注意带了括号)时,尽管已经执行完 print_msg( ) ,但是函数相关信息仍然保留。
通过这种技术,一些数据(“Hello”)和代码绑定在一起,我们称之为closure in Python。
即使变量不在这个域中了或者函数本身从现有命名空间移除了,在enclosing范围的值还是存在。
>>> del print_msg
>>> another()
Hello
>>> print_msg("Hello")
Traceback (most recent call last):
...
NameError: name 'print_msg' is not defined
3. When do we have a closure
在上面例子中,nested函数引用了enclosing域中的值,这是我们就有了一个closure。
在python创建closure的几大准则:
- 我们必须有nested函数(即函数嵌套函数)
- nested函数必须引用在enclosing域中定义的值
- enclosing函数必须返回nested函数
4. When to use closure
所以用closure有什么好处吗?
Closure可以避免使用global values,提供某些形式的data hiding。也能提供面向对象的问题方案。
closure也是一个class编程方式的替代方案,而且更优雅、高级。但是当attributes和methods越来越多时,还是用class比较好。
def make_multiplier_of(n):
def multiplier(x):
return x * n
return multiplier
# Multiplier of 3
times3 = make_multiplier_of(3)
# Multiplier of 5
times5 = make_multiplier_of(5)
# Output: 27
print(times3(9))
# Output: 15
print(times5(3))
# Output: 30
print(times5(times3(2)))