美文网首页
python的装饰器之我解

python的装饰器之我解

作者: Edward_f0cus | 来源:发表于2018-01-01 21:11 被阅读19次

本质上来说, 就是闭包加python的一个语法糖.
亲们,让我们从头说起:

python中一切皆对象,方法也是一个对象.
def foo():
      print 'this is func foo'

isinstance(foo, object)
True

所以TA可以被作为方法的形参传进去, 也可以作为return value被return.
我们先记下这一点, 后面会详细说明.

内嵌方法(nested function):

python允许在方法内部定义一个方法, 内部方法可以引用操作外部方法的变量.

def outer():
    para = 1
    print 'this is outer func'
    def inner():
        print 'this is inner func'
        print 'outer para in inner is %s' % para
        return para
    return inner()

 print outer()
 print para 

输出如下:

  this is outer func
  this is inner func
  outer para in inner is 1
  1
  NameError: name 'para' is not defined

一个方法内部变量的生命周期, 应该是在执行这个方法时被define, 方法执行完毕后被delete. 在这个例子里print outer()之后, para必定不能再被使用, 如果再加一个print para, 必定会报错. okay, 目前为止, 一切都是按我们预想的来, 看起来也很好理解.

闭包(closures)

我们把上面的例子稍微改一改:

  def outer(): 
        para = 1 
        print 'this is outer func' 
        def inner(): 
                print 'this is inner func' 
                print 'outer para in inner is %s' % para
                return para
        return inner

  closure = outer()

输出如下:

this is outer func

这次我们把outer()的返回值改成inner这个方法本身。是不是看起来有点怪怪的?前面已经提到,方法在python里本身也是一个对象,so, why not?
从输出可以看出,调用outer()之后,inner方法并没有被执行。这也是好理解的。在python中,“()”是调用操作符,既然outer返回的是inner而不是inner(),说明inner就没有被call,所以它没有执行。cool,到这里虽然看起来有些复杂,但还是在比较好理解的范围之内。
我们继续:

 print closure()

输出:

 this is inner func
 outer para in inner is 1
 1

这个是不是就有点难理解了?outer方法已经被执行完了,那么para的生命周期已经结束,inner怎么还可以用它?不报错?
** 这就是python对闭包的支持。**
如果我们dir一个方法(dir(closure)),会看到有func_closure这么一个内置的属性。如果此方法是一个闭包,那就会把闭包里用到的对象塞到这个属性里。

print closure.func_closure

输出:

(<cell at 0x7f42d46dd280: int object at 0x16cd158>,)

这个int对象就是我们例子里可爱的para.

装饰器(decorator):

升级一下上个例子, 给outer改个名字,同时传个参数。

 def decor(func):
        print 'this is func decor'
        def inner():
                  print 'this is inner func'
                  print 'call func in inner.'
                  func()
        return inner

 def foo():
          print 'this is func foo'

 foo = decor(foo)
 foo()

输出:

this is func decor
this is inner func
call func in inner.
this is func foo

改名之后的方法叫decor,加了个参数func。把decor(foo)重新赋值给foo, 并执行foo。
结果是原有的foo被执行,还有我们的inner。是不是很酷,相当于给foo加了个包装(wrapper)。
我们离胜利仅剩一步!
@这个符号是python对闭包采用的一个语法糖(syntax suger)。

 def decor(func):
        print 'this is func decor'
        def inner():
                  print 'this is inner func'
                  print 'call func in inner.'
                  func()
        return inner
 @decor
 def foo():
          print 'this is func foo'

 # foo = decor(foo)
 foo()

一样的输出:

this is func decor
this is inner func
call func in inner.
this is func foo

用了@语法糖,就相当于去掉了foo = decor(foo)这一步,让代码看起来更优雅,更readable。
That's it。这就是装饰器。
如需转载, 请注明出处!谢谢

还可以用class来做装饰器,请参考:class decorator
也可以给装饰器传参数,请参考:decorator with arguments

相关文章

  • python的装饰器之我解

    本质上来说, 就是闭包加python的一个语法糖.亲们,让我们从头说起: python中一切皆对象,方法也是一个对...

  • 9个Python 内置装饰器: 显著优化代码

    装饰器是应用“Python 之禅”哲学的最佳 Python 特性。装饰器可以帮助您编写更少、更简单的代码来实现复杂...

  • 装饰器五部曲

    听说你学不会装饰器?Python基础之装饰器五部曲,带你轻轻松松学会装饰器 装饰器(decorator)是Pyth...

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • Python 入门之 Python三大器 之 装饰器

    Python 入门之 Python三大器 之 装饰器 1、开放封闭原则: (1)代码扩展进行开放 ​ 任何一个程序...

  • Python ☞ day 5

    Python学习笔记之 装饰器& 偏函数 & 异常处理 & 断言 & 文件读写 &编码与解码 装饰器 概念:是一个...

  • Python闭包和装饰器

    本节课纲: 魔法方法之_call_ 闭包 装饰器 装饰器实例 一、魔法方法之_call_ 在Python中,函数其...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python进阶——面向对象

    1. Python中的@property   @property是python自带的装饰器,装饰器(decorat...

网友评论

      本文标题:python的装饰器之我解

      本文链接:https://www.haomeiwen.com/subject/nshxnxtx.html