zoukankan      html  css  js  c++  java
  • Python 闭包(Closure)

    Python  闭包 (Closure)

    这里介绍一下python 的闭包

    基本概念

    闭包(closure)是函数式编程的重要的语法结构。

    函数式编程的一个特点就是,允许把函数本身作为参数传入另一个函数,还允许返回一个函数!

    Python对函数式编程提供部分支持。由于Python允许使用变量,因此,Python不是纯函数式编程语言。

    闭包(closure)是函数式编程的重要的语法结构。函数式编程是一种编程范式 (而面向过程编程和面向对象编程也都是编程范式)。

    在面向过程编程中,我们见到过函数(function);在面向对象编程中,我们见过对象(object)。

    函数和对象的根本目的是以某种逻辑方式组织代码,并提高代码的可重复使用性(reusability)。

    闭包也是一种组织代码的结构,它同样提高了代码的可重复使用性。

    不同的语言实现闭包的方式不同。Python以函数对象为基础,

    为闭包这一语法结构提供支持的 (我们在特殊方法与多范式中,已经多次看到Python使用对象来实现一些特殊的语法)。

    Python一切皆对象,函数这一语法结构也是一个对象。

    在函数对象中,我们像使用一个普通对象一样使用函数对象,比如更改函数对象的名字,或者将函数对象作为参数进行传递。

    函数对象的作用域

    和其他对象一样,函数对象也有其存活的范围,也就是函数对象的作用域。

    函数对象是使用def语句定义的,函数对象的作用域与def所在的层级相同。

    比如下面代码,我们在next函数的隶属范围内定义的函数test,就只能在test的隶属范围内调用。

    def test():
    
        def next():
            print('next')
    
        print('test')
    
    test()
    
    # 执行结果  
    > test

    再看下面代码

    def test():
    
        def next():
            print('next')
        next()
        print('test')
        next()
    test()
    
    # 执行结果
    > next
    > test
    > next

    引入闭包

    函数是一个对象,所以可以作为某个函数的返回结果。

    def hello(greet):
    
        def setName(name):
            print(greet,name)
        return setName
    
    Hello = hello("Good Morning")
    
    Hello('Yang')
    
    print(dir(Hello))
    
    print(Hello.__closure__)
    
    print(Hello.__closure__[0].cell_contents)
    
    print(Hello.__name__)
    
    print(id(Hello))
    
    Hellob = hello("Good Afternoon")
    
    Hellob('Yang')
    print(Hello.__name__)
    
    print(id(Hellob))
    
    # 执行结果
    #> Good Morning Yang
    #> ['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
    #> (<cell at 0x0000026D9A8078B8: str object at 0x0000026D9A966370>,)
    #> Good Morning
    #> setName
    #> 1779595040560
    #> Good Afternoon Yang
    #> setName
    #> 1779595040696

    闭包只是在表现形式上跟函数类似,但实际上不是函数。

    从代码的结果中可以看到,闭包在运行时可以有多个实例,不同的引用环境变量(这里就是greet变量)和相同的函数(这里就是setName)组合可以产生不同的实例。

    一个函数和它的环境变量合在一起,就构成了一个闭包(closure)。在Python中,所谓的闭包是一个包含有环境变量取值的函数对象。环境变量取值被保存在函数对象的__closure__属性中。

    __closure__里包含了一个元组(tuple)。这个元组中的每个元素是cell类型的对象。我们看到第一个cell包含的就是Good Morning,也就是我们创建闭包时的环境变量greet的取值。

     

    Python中怎么创建闭包

    在Python中创建一个闭包可以归结为以下三点:

    • 闭包函数必须有内嵌函数
    • 内嵌函数需要引用该嵌套函数上一级中的变量
    • 闭包函数必须返回内嵌函数

    通过这三点,就可以创建一个闭包

    闭包实例

    def closureFun():
        '''闭包'''
        a = 5
        def add(x):        # 1 闭包函数必须有内嵌函数
            return x + a   # 内嵌函数需要引用该嵌套函数上一级中的变量 a
        return add         # 闭包函数必须返回内嵌函数
    print(locals())
    
    c = closureFun()   # 实例化函数 closureFun  返回 函数add
    sum = c(6)         # 调用add ,并传参 ,此时返回 x + a = 6 + 5 = 11
    
    print(sum) # 11
    
    print(globals())

    Python中的内建函数locals()和globals()可以用来查看不同namespace中定义的元素。

    总结

    本文介绍了如何通过Python创建一个闭包,以及Python创建的闭包是如何工作的。

  • 相关阅读:
    一次函数(好难的一次函数)
    脱水缩合(大搜索)
    背单词
    仙人掌(cactus)
    LYK 快跑!(LYK别打我-)(话说LYK是谁)
    巧克力棒
    选数字(贪心+枚举)
    看程序写结果(program)
    np问题
    IUYYLIUIU
  • 原文地址:https://www.cnblogs.com/BlueSkyyj/p/8884236.html
Copyright © 2011-2022 走看看