Python 闭包

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__ 属性,如果它是闭包函数,则返回一个单元格对象元组

参考上面的例子,我们知道 times3times5 是闭包函数。

你觉得这篇文章有帮助吗?

我们的高级学习平台,凭借十多年的经验和数千条反馈创建。

以前所未有的方式学习和提高您的编程技能。

试用 Programiz PRO
  • 交互式课程
  • 证书
  • AI 帮助
  • 2000+ 挑战