Python - 闭包(closures)



什么是闭包?

Python 闭包(closures)是一个嵌套函数,它可以从已完成执行的封闭函数中访问变量。此类变量未绑定到 local 范围内。要使用不可变变量(数字或字符串),我们必须使用 non-local 关键字。

Python 闭包的主要优点是我们可以帮助避免使用全局值并提供某种形式的数据隐藏。它们用于 Python 装饰器。

闭包与嵌套函数密切相关,并允许内部函数捕获和保留封闭函数的本地状态,即使在外部函数完成执行后也是如此。理解闭包需要熟悉嵌套函数、变量范围以及 Python 如何处理函数对象。

  • 嵌套函数:在 Python 中,可以在其他函数中定义函数。这些函数称为嵌套函数或内部函数。
  • 访问封闭范围:内部函数可以从封闭(即外部范围)访问变量。这就是 闭包(Closure) 发挥作用的地方。
  • 保留状态:当内部函数(即闭包)从其封闭范围内捕获并保留变量时,即使外部函数已经完成执行或范围不再可用。

嵌套函数

Python 中的嵌套函数是指在另一个函数中定义一个函数的做法。这个概念使我们能够更有效地组织代码、封装功能并管理变量范围。

以下是在 functionA 中定义 functionB 的嵌套函数示例。然后从外部函数的作用域内调用 Inner 函数。


def functionA():
	 	print ("Outer function")
	 	def functionB():
	 	 	 print ("Inner function")
	 	functionB()

functionA()

输出

Outer function
Inner function

如果外部函数收到任何参数,则可以将其传递给内部函数,如下例所示。


def functionA(name):
	 	print ("Outer function")
	 	def functionB():
	 	 	 print ("Inner function")
	 	 	 print ("Hi {}".format(name))
	 	functionB()
	 	
functionA("Python")

输出

Outer function
Inner function
Hi Python

 

变量范围

当创建一个闭包时,即一个从其封闭范围内捕获变量的内部函数,即使在外部函数完成执行后,它仍然保留对这些变量的访问。此行为允许闭包“记住”并操作封闭作用域中的变量值。

以下是具有变量范围的闭包的示例 -


def outer_function(x):
	 	 y = 10
	 		
	 	 def inner_function(z):
	 	 	 	 return x + y + z 	# x and y are captured from the enclosing scope
	 		
	 	 return inner_function

closure = outer_function(5)
result = closure(3)
print(result) 	

输出

18

创建 Closure

在 Python 中创建闭包涉及在外部函数中定义嵌套函数并返回内部函数。闭包对于从封闭作用域中捕获和保留变量的状态很有用。

在下面的示例中,我们有一个 functionA 函数,它创建并返回另一个函数 functionB。嵌套的 functionB 函数是闭包。

外部 functionA 函数返回一个 functionB 函数并将其分配给 myfunction 变量。即使它已经完成了执行。但是,打印机闭包仍然可以访问 name 变量。

以下是在 python 中创建闭包的示例 -


def functionA(name):
	 	name ="New name"
	 	def functionB():
	 	 	 print (name)
	 	return functionB
	 	
myfunction = functionA("My name")
myfunction()

输出

New name

nonlocal 关键字

在 Python 中,nonlocal 关键字允许访问本地范围之外的变量。这在闭包中用于修改存在于 outer 变量范围内的不可变变量。下面是带有 nonlocal 关键字的闭包示例。


def functionA():
	 	counter =0
	 	def functionB():
	 	 	 nonlocal counter
	 	 	 counter+=1
	 	 	 return counter
	 	return functionB

myfunction = functionA()

retval = myfunction()
print ("Counter:", retval)

retval = myfunction()
print ("Counter:", retval)

retval = myfunction()
print ("Counter:", retval)

输出

Counter: 1
Counter: 2
Counter: 3