• python闭包closure


    在讨论闭包之前,先总结一下python的命名空间namespace,一般的语言都是通过namespace来识别名字标识,无论是变量,对象,函数等等。python划分3个名字空间层次,local:局部,标识为当前函数内,当前类内,比如局部变量。global:全局,标识当前模块,也就是当前文件,比如全局变量等。最后一类 built-in,内建,这个是作用域比较大,跨模块(文件)都可以标识,比如我们自建的文件中,引用内建函数dir(), 这就是一个典型的例子,自建的文件中能够并没有声明dir(),但由于dir()是built_in内建函数,故在所有文件或模块都可以引用。

    再来讨论闭包:百度上对闭包的定义是:闭包是指可以包含自由变量的代码块。定义简单明了,也有把自由变量成为环境变量的。紧接着定义什么是自由变量或环境变量:这些变量不是在这个代码块内或者任何全局上下文中定义的,而是在定义代码块的环境中定义(局部变量)。结合namespace的概念,自由变量的位置:既不在函数local范围内,也不在全局global范围内,而是在两个函数的作用域之间。举个例子:

     1 def numFunc(a, b):
     2     num = 100
     3     num2 = 200
     4     num3 = 300
     5     print('print s in numbunc', s)
     6 
     7     def addfunc(a, b):
     8         s = 'string in addfunc'
     9         x = num
    10         y = num3
    11         print('print s in addFunc', s)
    12 
    13     return addfunc

    num, num2, num3, 这三个变量符合自由变量的描述,既不在局部local内,也不再全局global内。而是在两个函数的作用域之间。

    所以咱们说白了,闭包从形式上说,就是函数内嵌一个函数。但是还需满足两个条件,1.内层函数引用环境变量(自由变量)2外部函数返值为内部函数名(一个返回函数的高阶函数)

    再来说闭包有什么用? 闭包减少了参数的传递数量, 设计闭包是为了增加代码重复利用。还有的文章中说到,闭包是为了方便并行计算设计的,随着我们深入学习,会继续充实这篇文章,发觉闭包的更多作用。另外是不是跟装饰器有点像呢?其实本质上,decorator就是一个返回函数的高阶函数,闭包也是一个返回函数的高阶函数。从这个角度上说 装饰器也是闭包,闭包也是装饰器。区别在于装饰器希望在代码运行期间动态增加功能,闭包希望简化参数的调用提高代码利用率

    闭包的特性 __closure__

    __closure__是内部函数的一个属性,用来保存环境变量,用type()函数看一下,__closure__是一个tulple, 还以上边的代码为例,我们看一下环境变量都包含什么,什么样的变量可以记录到环境变量中得以保存:

    从结果中我们看到,num和num3被保存了下来,而num2没有被保存,原因很简单,因为定义中,内部函数必须引用自由变量,num2没有被引用。

    再来看一个例子,帮助我们理解,解释器是如何保存环境变量到__closure__中来的,我把廖雪峰的例子做了修改:

     1 def count():
     2     fs = []
     3     for i in range(1, 4):
     4         def f():
     5              return i*i 6  7     return f
     8 
     9 f = count()
    10 x = None
    11 x = f()12 pass

    我们单步跟进,发现,在每次循环中,f()只是声明,没有执行,所以每次循环,return i*i并没有被执行。循环结束i = 3,在这时,count()函数返回,解释器将环境变量 i 保存到__closure__中去,i = 3,打扫好现场,count()的堆栈,上下文撤销

    所有环境变量都是在函数闭包声明结束是完成初始化。下面我们用一个例子来说明:

    第一步:   定义闭包之前,__closure__这个属性没有值

    第二步:最关键的一步: 我们发现,在闭包声明结束的时候,内部函数的还将变量就已经确定下来了,不需要等到执行内部函数才确定环境变量。

      

    闭包的不习惯

    在c/c++中好像没有闭包的概念,也没有环境变量(自由变量)的概念,所以函数包含函数,或者外部函数返回内部函数,会造成异常,因为内部函数返回,堆栈消失,所有内部变量都不存在了。而python的闭包设计是允许返回局部变量的,这给我们这些从c/c++转过来的少年带来了很大的不适应,总感觉要出大事,这时候想想__closure__属性,python的闭包设计使推出内部函数后,没有回收内部函数的部分资源,而是作为环境变量保存下来了,慢慢习惯。

  • 相关阅读:
    硬件的效率与一致性
    深入理解SPI机制-服务发现机制
    spring 之7种重要设计模式
    list里放map list 放list
    jvm 三种编译
    几种不同格式的json解析
    Java知识点梳理——集合
    判断2个list中是否有相同的数据(相交)Collections.disjoint
    键相同,比较两个map中的值是否相同
    Map类型数据导出Excel--poi
  • 原文地址:https://www.cnblogs.com/fanyuchen/p/7228174.html
Copyright © 2020-2023  润新知