Python 闭包是一个嵌套的函数,它允许我们即使在外部函数关闭后仍然访问外部函数的变量。
在学习闭包之前,我们先回顾一下 Python 中嵌套函数的概念。
Python 中的嵌套函数
在 Python 中,我们可以在另一个函数内部创建一个函数。这被称为嵌套函数。例如,
def greet(name):
# inner function
def display_name():
print("Hi", name)
# call inner function
display_name()
# call outer function
greet("John")
# Output: Hi John
在上面的示例中,我们在 greet()
函数内部定义了 display_name()
函数。
这里,display_name()
是一个嵌套函数。嵌套函数与普通函数的工作方式类似。当在 greet()
函数内部调用 display_name()
时,它会执行。
Python 闭包
正如我们已经讨论过的,闭包是一个嵌套函数,它帮助我们即使在外部函数关闭后仍然访问外部函数的变量。例如,
def greet():
# variable defined outside the inner function
name = "John"
# return a nested anonymous function
return lambda: "Hi " + name
# call the outer function
message = greet()
# call the inner function
print(message())
# Output: Hi John
在上面的示例中,我们创建了一个名为 greet()
的函数,它返回一个嵌套的匿名函数。
这里,当我们调用外部函数时,
message = greet()
返回的函数现在被赋值给 message 变量。
此时,外部函数的执行已完成,因此 name 变量应该被销毁。但是,当我们使用以下方式调用匿名函数时:
print(message())
我们能够访问外部函数的 name 变量。
这是可能的,因为嵌套函数现在作为一个闭包,即使外部函数执行完毕后,它也会将其作用域内的外部作用域变量封闭起来。
让我们再看一个例子来阐明这个概念。
示例:使用 Python 闭包打印奇数
def calculate():
num = 1
def inner_func():
nonlocal num
num += 2
return num
return inner_func
# call the outer function
odd = calculate()
# call the inner function
print(odd())
print(odd())
print(odd())
# call the outer function again
odd2 = calculate()
print(odd2())
输出
3 5 7 3
在上面的例子中:
odd = calculate()
此代码执行外部函数 calculate()
并将闭包返回给奇数。
这就是为什么即使在外部函数完成之后,我们仍然可以访问 calculate()
的 num 变量。
同样,当我们使用以下方式调用外部函数时:
odd2 = calculate()
会返回一个新的闭包。因此,当我们调用 odd2()
时,我们再次得到 3。
何时使用闭包?
那么闭包有什么用呢?
闭包可以用来避免全局变量并提供数据隐藏,并且可以作为单方法或少数方法的简单情况的优雅解决方案。
然而,对于具有多个属性和方法的较大情况,类实现可能更合适。
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)))
Python 装饰器也大量使用了闭包。
最后,值得指出的是,可以找出闭包函数中封装的值。
所有函数对象都有一个 __closure__
属性,如果它是闭包函数,则返回一个单元格对象元组。
参考上面的例子,我们知道 times3
和 times5
是闭包函数。