Python 简明教程

Python - Closures

What is a Closure?

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

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

闭包与嵌套函数密切相关,允许内部函数在外部函数完成执行后捕获和保留封闭函数的局部状态。理解闭包需要了解嵌套函数、变量作用域以及 Python 如何处理函数对象。

  1. Nested Functions: 在 Python 中,函数可以在其他函数内定义。这些称为嵌套函数或内部函数。

  2. Accessing Enclosing Scope: 内部函数可以访问封闭(即外部)作用域中的变量。这就是闭包发挥作用的地方。

  3. Retention of State: 即便是外层函数已经执行完毕或者作用域已经不在,当内部函数,即闭包,从其包围作用域捕获并保留变量时。

Nested Functions

Python 中的嵌套函数是指在一个函数中定义另一个函数的做法。此概念可让我们更有效地组织代码,封装功能并管理变量作用域。

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

Example

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

functionA()

Output

Outer function
Inner function

如果外层函数接收到任何参数,它可按以下示例所示传递给内部函数。

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

functionA("Python")

Output

Outer function
Inner function
Hi Python

Variable Scope

当闭包创建(即,捕获来自其包围作用域的变量的内部函数)时,即使外层函数已经执行完毕,它仍可保留对那些变量的访问。此行为可让闭包“记住”并操作来自包围作用域的变量的值。

Example

以下是包含可变作用域的闭包的示例 −

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)

Output

18

Creating a closure

创建 Python 中的闭包包括定义外层函数中的嵌套函数并返回内部函数。闭包可用于捕获和保留来自包围作用域的变量的状态。

Example

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

外层 functionA 函数返回 functionB 函数,并将其指定给 myfunction 变量。即便它已经执行完毕。然而,printer 闭包仍然有权访问 name 变量。

以下是创建 Python 中闭包的示例 −

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

myfunction = functionA("My name")
myfunction()

Output

New name

nonlocal Keyword

在 Python 中,nonlocal 关键字允许访问位于局部作用域之外的变量。这在闭包中用于修改存在于外层变量作用域中的不可变变量。以下是包含 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)

Output

Counter: 1
Counter: 2
Counter: 3