zoukankan      html  css  js  c++  java
  • python闭包和装饰器(转)

     

    一、python闭包

    1、内嵌函数

    >>> def func1():
    ...     print ('func1 running...')
    ...     def func2():
    ...             print ('func2 running...')
    ...     func2()
    ... 
    >>> func1()
    func1 running...
    func2 running...

    内部函数func2作用域都在外部函数func1作用域之内 
    如果试图在外部函数的外部调用内部函数将会报错

    >>> func2()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'func2' is not defined

    如果试图在一个内部函数里对外部作用域(不包括外部函数的外部作用域)的变量进行引用,内部函数就会被认为是闭包

    >>> def FuncX(x):
    ...     def FuncY(y):
    ...             return x*y
    ...     return FuncY

    对于FuncY函数来说,对在FuncX函数的整个作用域(FuncY函数的非全局作用域的外部作用)的变量x进行引用,自此就可以说FuncY函数就是所谓的闭包

    >>> f = FuncX(8)
    >>> f
    <function FuncY at 0x7f3a436fc2a8>
    >>> type(f)
    <type 'function'>
    >>> f(10)
    80
    >>> FuncX(7)(8)
    56

    由于闭包本身是基于内部函数这一概念而来,所以不能在外部函数的外部作用域对内部函数进行调用

    >>> FuncY(8)
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
    NameError: name 'FuncY' is not defined

    既然是基于内部函数这一概念而来,自然对于内部函数来说对引用外部函数作用域内的变量进行修改,将会启动解释器的屏蔽机制

    >>> def Func1():
    ...     x = 233
    ...     def Func2():
    ...             x *=x
    ...             return x
    ...     return Func2()
    ... 
    >>> Func1()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "<stdin>", line 6, in Func1
      File "<stdin>", line 4, in Func2
    UnboundLocalError: local variable 'x' referenced before assignment

    x*=x的左值此时是内部函数作用域里的变量,此时试图将没有定义的数据进行平方操作,因此报错

    >>> def Func1():
    ...     x = 233
    ...     def Func2():
    ...             x = 321
    ...             return x
    ...     return Func2()
    ... 
    >>> Func1()
    321

    内部函数创建x变量并且屏蔽外部函数作用域内的x变量

    python3之前的解决办法

    应用容器类型(list,tuple之类的)存放外部函数作用域的变量从而不会被屏蔽机制屏蔽掉,因为容器类型不是存放在栈里面

    >>> def Func1():
    ...     x = [233]
    ...     def Func2():
    ...             x[0] *= x[0]
    ...             return x[0]
    ...     return Func2()
    ... 
    >>> Func1()
    54289

    python3之后的解决办法:nonlocal关键字

    >>> def Func1():
    ...     x = 233
    ...     def Func2():
    ...     nonlocal x
    ...             x *= x
    ...             return x
    ...     return Func2()
    ... 
    >>> Func1()
    54289

    二、装饰器

    事实上,装饰器就是一种的闭包的应用,只不过其传递的是函数:

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

    闭包的作用

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

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

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

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

    转自:http://blog.csdn.net/ChangerJJLee/article/details/52598629

    https://segmentfault.com/a/1190000004461404

  • 相关阅读:
    Lucene in action 笔记 case study
    关于Restful Web Service的一些理解
    Lucene in action 笔记 analysis篇
    Lucene in action 笔记 index篇
    Lucene in action 笔记 term vector
    Lucene in action 笔记 search篇
    博客园开博记录
    数论(算法概述)
    DIV, IFRAME, Select, Span标签入门
    记一个较困难的SharePoint性能问题的分析和解决
  • 原文地址:https://www.cnblogs.com/shixisheng/p/7093800.html
Copyright © 2011-2022 走看看