Python Closures


在了解什么是闭包之前,我们必须首先了解什么是嵌套函数和非局部变量。

Python 中的嵌套函数

在另一个函数内部定义的函数称为嵌套函数。嵌套函数能够访问封闭范围的变量。

在Python中,这些非局部变量只能在其作用域内访问,而不能在其作用域外访问。这可以通过以下示例来说明:

  • Python3
# Python program to illustrate
# nested functions
def outerFunction(text):

    def innerFunction():
        print(text)

    innerFunction()


if __name__ == '__main__':
    outerFunction('Hey!')

输出:

Hey!

正如我们所看到的,innerFunction()可以在outerFunction主体内部轻松访问,但不能在其主体外部访问。因此,在这里,innerFunction() 被视为使用文本作为非局部变量的嵌套函数。

什么是 Python 闭包

Python 中的闭包是一个函数对象,它会记住封闭范围内的值,即使它们不存在于内存中。

  • 它是一个将函数与环境一起存储的记录:将函数的每个自由变量(在本地使用但在封闭范围内定义的变量)与创建闭包时绑定名称的值或引用相关联的映射。
  • 与普通函数不同,闭包允许函数通过闭包的值或引用的副本来访问这些捕获的变量,即使在函数作用域之外调用该函数也是如此。

  • Python3

# Python program to illustrate
# closures
def outerFunction(text):

    def innerFunction():
        print(text)

    # Note we are returning function
    # WITHOUT parenthesis
    return innerFunction

if __name__ == '__main__':
    myFunction = outerFunction('Hey!')
    myFunction()

输出:

omkarpathak@omkarpathak-Inspiron-3542:
~/Documents/Python-Programs/$ python Closures.py 
Hey!

从上面的代码可以看出,Python 中的闭包有助于调用其作用域之外的函数。函数innerFunction的作用域仅在outerFunction 内部。但是通过使用 Python 闭包,我们可以轻松扩展其范围以调用其范围之外的函数。

  • Python3
# Python program to illustrate
# closures
import logging
logging.basicConfig(filename='example.log',
                    level=logging.INFO)

def logger(func):
    def log_func(*args):
        logging.info(
            'Running "{}" with arguments {}'.format(func.__name__,
                                                    args))
        print(func(*args))

    # Necessary for closure to
    # work (returning WITHOUT parenthesis)
    return log_func         

def add(x, y):
    return x+y

def sub(x, y):
    return x-y

add_logger = logger(add)
sub_logger = logger(sub)

add_logger(3, 3)
add_logger(4, 5)

sub_logger(10, 5)
sub_logger(20, 10)

输出:

omkarpathak@omkarpathak-Inspiron-3542:
~/Documents/Python-Programs/$ python MoreOnClosures.py 
Running "add" with arguments6
9
5
10

~/Documents/Python-Programs/$ cat example.log
INFO:root:Running "add" with arguments (3, 3)
INFO:root:Running "add" with arguments (4, 5)
INFO:root:Running "sub" with arguments (10, 5)
INFO:root:Running "sub" with arguments (20, 10)

这里需要注意的重要一点是,我们可以借助 closure属性来了解闭包中存储了哪些变量,该属性利用单元对象来存储外部函数的变量,因此,即使外部函数终止,闭包也可以使用这些变量。

何时以及为何使用闭包

  1. 由于 Python 闭包用作回调函数,因此它们提供了某种数据隐藏。这有助于我们减少全局变量的使用。
  2. 当代码中的函数很少时,Python 中的闭包被证明是一种有效的方法。但如果我们需要有很多功能,那么就选择类(OOP)。
  3. 我们可能在全局范围内有一些有时不被许多函数使用的变量。不要在全局范围内定义变量,而是考虑使用闭包。它们可以在外部函数中定义并在内部函数中使用。Python 闭包对于避免使用全局范围也很有用。
  4. Python 编程语言中的类始终具有 init 方法。如果您只有一个额外的方法,一个优雅的解决方案是使用闭包而不是类。因为这样提高了代码的可读性,甚至减少了程序员的工作量。因此,Python 中的闭包可用于避免不必要地使用类。


原文链接:codingdict.net