闭包的更好示例?

13 投票
5 回答
13659 浏览
提问于 2025-04-15 22:30

我正在通过《Dive Into Python 3》这本书学习Python。我觉得这本书不错,但我不太理解第6.5节中用来介绍闭包的例子

我的意思是,我看得懂它是怎么工作的,我觉得这真的很酷。但我觉得没有什么实际的好处:在我看来,似乎只要在循环中逐行读取规则文件,然后对每一行进行搜索和替换,就能得到同样的结果。

有人能帮我:

  • 要么解释一下在这个例子中使用闭包是如何改善代码的(比如说,更容易维护、扩展、重用或调试?)

  • 要么推荐一些其他真实的代码例子,让我看看闭包是如何发挥作用的?

5 个回答

2

这里有一个关于闭包使用的例子,主要是获取配置:

def confmaker():
   cf=ini_conf()
   def clo(*args):
      return cf.get(*args)
   return clo

cfget=confmaker()

cfget(...)

在这个例子中,ini_conf 只被调用了一次。我的理解是,闭包可以避免使用全局变量(比如 cf),而且使用起来更简单。

2

这段话可能在你能访问整个代码时看起来没什么用,或者当你不考虑代码重用时,但其实它在把逻辑分开成不同的、可以重复使用的模块时非常强大和有用。这些模块可以让不同的开发者并行工作。如果你只是从文件中读取模式字符串,那么每个模块都得知道这个文件,还得传来传去那些烦人的模式字符串列表。如果你把系统改成从一个网址获取模式字符串,而不是从文件中读取,那可能会完全搞坏你的整个代码。相反,如果你的处理逻辑只需要一个回调函数或者几个回调函数,而你有另一个模块可以动态构建这些函数,使用文件中的内容,那么只有构建函数的那个部分需要改变。这就是动态创建函数的强大之处。

26

装饰器是闭包的一个例子。比如说,

def decorate(f):
    def wrapped_function():
        print("Function is being called")
        f()
        print("Function call is finished")
    return wrapped_function

@decorate
def my_function():
    print("Hello world")

my_function()

这个叫做 wrapped_function 的函数就是一个闭包,因为它可以访问它所在范围内的变量——特别是参数 f,也就是原始函数。闭包让你能够访问这些变量。

闭包还可以让你在多次调用一个函数时保持状态,而不需要使用类:

def make_counter():
    next_value = 0
    def return_next_value():
        nonlocal next_value
        val = next_value
        next_value += 1
        return val
    return return_next_value

my_first_counter = make_counter()
my_second_counter = make_counter()
print(my_first_counter())
print(my_second_counter())
print(my_first_counter())
print(my_second_counter())
print(my_first_counter())
print(my_second_counter())

另外,绑定方法在技术上也是闭包(虽然它们的实现方式可能不同)。绑定方法是类中的成员函数,已经和它的类绑定在一起:

import sys
w = sys.stdout.write
w("Hello\n")

w 本质上是一个闭包,它引用了 sys.stdout 对象。

最后,我没有读过那本书,但快速浏览你提到的章节后,我觉得很失望——它的解释方式太绕了,根本没法清楚地说明闭包是什么。

撰写回答