代码之家  ›  专栏  ›  技术社区  ›  max

Python闭包示例代码

  •  13
  • max  · 技术社区  · 14 年前

    我正在学习Python Dive Into Python 3 书。我喜欢,但我不明白 example used to introduce Closures

    我是说,我知道它是怎么工作的,我觉得它很酷。但我没有看到任何真正的好处:在我看来,只要在循环中逐行读取规则文件,并对读取的每一行执行搜索/替换,就可以获得相同的结果。

    有人能帮我:

    • 或者理解为什么在本例中使用闭包可以改进代码(例如,更易于维护、扩展、重用或调试?)

    • 或者建议一些其他真实代码示例的源代码,在这些示例中闭包是真正的亮点?

    5 回复  |  直到 5 年前
        1
  •  26
  •   Matthew Murdoch    9 年前

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

    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

    最后,我还没读过那本书,但是快速阅读一下你链接的那一章,我很没印象——它太迂回了,不能作为闭包的解释。

        2
  •  2
  •   Michael Aaron Safyan    14 年前

    当您有权访问整个代码库或者没有考虑到可重用性时,这似乎不是特别有用,但是当您尝试将逻辑分离为不同的、可重用的模块(这些模块可以由不同的开发人员并行实现)时,这是非常强大和有用的。如果您只是简单地从文件中读取模式字符串,那么每个模块都必须知道这个文件,并传递恼人的模式字符串列表。如果您更改了系统,使模式字符串来自URL而不是文件,则可能会完全破坏整个代码库。另一方面,如果处理逻辑只接受一个回调函数或几个回调函数,然后有另一个模块使用文件中的内容动态构造函数,那么只有构造函数的组件需要更改。这就是动态创建函数的能力。

        3
  •  2
  •   whi    12 年前

    下面是get configures的闭包用法:

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

    这里ini\ U conf只调用一次。在我的理解中,闭包避免了全局变量(比如cf),并使使用变得简单。

        4
  •  1
  •   user3842449 user3842449    9 年前

    尼尔斯Bom写入(带编辑):

    尼尔斯的问题促使我勾勒出第六章的发展脉络,以便准确地理解作者试图展示的内容。在所提供的开发过程中,有许多经验值得我们学习,而且不仅仅是闭包,还有编码方面的最佳实践。

    这个练习帮助我理解了如何使用生成器来替换替代的、不那么抽象的和更加复杂的实现。从6.2到6.6的材料的发展是教育性的,足以在这里勾勒出来。

    因此,我从尼尔斯的第二点开始,关于在6.3中将规则分解为单独的函数,作为草图的一个部分:

    为什么在本例中使用闭包可以改进代码?

    添加这种抽象级别值得吗?嗯,还没有。

    还有第6.4-6.6节需要完成。闭包的故事,在本例中,构建复数化生成器是一步一步完成的,从名为复数(名词)的模块中的硬编码规则开始。因此,从第一节开始,总结我们的方法,直到本章结束,我们有以下内容。

    6.2让我们使用正则表达式:在这里,作者利用这个机会来加强和扩展我们对正则表达式的理解,在最初的复数函数中硬编码复数规则。

    6.3. 函数列表:将复数函数中硬编码的规则抽象为几个独立函数。这是下一节的“垫脚石”。但是它也证明了match_sxz()和match_sxz()的用法之间有一个重要的区别。

    6.6生成器:生成器是一个通用的复数()函数,它解析规则文件,检查是否匹配,如果合适,应用规则,然后转到下一个规则。这是一个闭包的例子。

    一个相对简单而漂亮的开发,足够复杂到有用,并且可以扩展到其他类型的问题,特别是在文本模式识别中。

        5
  •  0
  •   Ignacio Vazquez-Abrams    14 年前

    在循环中逐行读取规则文件

    循环中的一行一行

    这将推动整个地板性能。读一次,申请多次。