zoukankan      html  css  js  c++  java
  • 闭包函数

    1.闭包函数定义

       在通过Python的语言介绍一下,一个闭包就是你调用了一个函数A,这个函数A返回了一个函数B给你。这个返回的函数B就叫做闭包。你在调用函数A的时候传递的参数就是自由变量。

    举个例子:

     
    def func(name):
        def inner_func(age):
            print 'name:', name, 'age:', age
        return inner_func
    
    bb = func('the5fire')
    bb(26)  # >>> name: the5fire age: 26

    这里面调用func的时候就产生了一个闭包——inner_func,并且该闭包持有自由变量——name,因此这也意味着,当函数func的生命周期结束之后,name这个变量依然存在,因为它被闭包引用了,所以不会被回收。

    2.nonlocal 语句

     

    在 python 的函数内,可以直接引用外部变量,但不能改写外部变量,因此如果在闭包中直接改写父函数的变量,就会发生错误:

    在 python 2 中可以在函数内使用 global 语句,但全局变量在任何语言中都不被提倡,因为它很难控制,python 3 中引入了 nonlocal 语句解决了这个问题:

    Nonlocal 与 global 的区别在于 nonlocal 语句会去搜寻本地变量与全局变量之间的变量,其会优先寻找层级关系与闭包作用域最近的外部变量。

    3.装饰器

    装饰器(Decorator)相对简单,咱们先介绍它:“装饰器的功能是将被装饰的函数当作参数传递给与装饰器对应的函数(名称相同的函数),并返回包装后的被装饰的函数”,听起来有点绕,没关系,直接看示意图,其中 a 为与装饰器 @a 对应的函数, b 为装饰器修饰的函数,装饰器@a的作用是:

    栗子:

    简而言之:@a 就是将 b 传递给 a(),并返回新的 b = a(b)

    栗子:

    上面使用@dobi来表示装饰器,其等同于:qinfeng = dobi(qinfeng)
    因此装饰器本质上就是个语法糖,其作用为简化代码,以提高代码可读性,运行上段代码的结果为:

     

    解析过程是这样子的:
    1.python 解释器发现@dobi,就去调用与其对应的函数( dobi 函数)
    2.dobi 函数调用前要指定一个参数,传入的就是@dobi下面修饰的函数,也就是 qinfeng()
    3.dobi() 函数执行,调用 qinfeng(),qinfeng() 打印“dobi”

    4闭包与装饰器

    上面已经简单演示了装饰器的功能,事实上,装饰器就是一种的闭包的应用,只不过其传递的是函数:

    @makeitalic 装饰器将函数 hello 传递给函数 makeitalic,函数 makeitalic 执行完毕后返回被包装后的 hello 函数,而这个过程其实就是通过闭包实现的。@makebold 也是如此,只不过其传递的是 @makeitalic 装饰过的 hello 函数,因此最后的执行结果 <b><i> 外层,这个功能如果不用装饰器,其实就是显式的使用闭包:

     

    5.闭包的作用

    闭包的最大特点是可以将父函数的变量与内部函数绑定,并返回绑定变量后的函数(也即闭包),此时即便生成闭包的环境(父函数)已经释放,闭包仍然存在,这个过程很像类(父函数)生成实例(闭包),不同的是父函数只在调用时执行,执行完毕后其环境就会释放,而类则在文件执行时创建,一般程序执行完毕后作用域才释放,因此对一些需要重用的功能且不足以定义为类的行为,使用闭包会比使用类占用更少的资源,且更轻巧灵活,现举一例:假设我们仅仅想打印出各类动物的叫声,分别以类和闭包来实现

    可以看到输出结果是完全一样的,但显然类的实现相对繁琐,且这里只是想输出一下动物的叫声,定义一个 Animal 类未免小题大做,而且 voice 函数在执行完毕后,其作用域就已经释放,但 Animal 类及其实例 dog 的相应属性却一直贮存在内存中:

    而这种占用对于实现该功能后,则是没有必要的。

    除此之外,闭包还有很多其他功能,比如用于封装等,另外,闭包有效的减少了函数参数的数目,这对并行计算非常有价值,比如可以让每台电脑负责一个函数,然后串起来,实现流水化的作业等。

  • 相关阅读:
    Mysql锁机制介绍
    开启Mysql慢查询来优化mysql
    开启mysql慢查询日志并使用mysqldumpslow命令查看
    MySQL MyISAM/InnoDB高并发优化经验
    UIPageControl
    UIPikerView的属性
    UIScrollView
    UISement属性
    UISlide属性
    UISwitch
  • 原文地址:https://www.cnblogs.com/hanxiaofeicf/p/7028781.html
Copyright © 2011-2022 走看看