首页 > 技术文章 > python 装饰器

smail-bao 2016-08-08 14:34 原文

因为函数是一个对象,且函数对象可以被赋值给一个变量,所以可以通过变量也可以调用函数

什么是装饰器:

我们把在不修改原函数的情况下,在代码运行期间动态的增加功能的方式,我们称之为装饰器(decorator),实质上装饰器就是一个返回函数的高阶函数而已,

比如说我们现在有一个函数是这样定义的:
def now():

   print '2013-12-25'

但是我想要在这个函数功能上再增加一个打印的功能,所以这里我们就要用到装饰器了(动态的增加新功能)

def log(func):
    def wrapper(*args,**kv):
        print 'call %s():' % func.__name__

        return func(*args,**kv)

@log

def now():

   print '2013-12-25'

装饰器接收一个函数作为他的参数,也就是说这里我们把now函数给传到我们定义的log函数里作为他的参数,这里我们通过python 的@语法,把装饰器放在函数的定义处

我们现在要是执行

now()

这个其实就是相当于执行了log(now)

返回的结果会是(因为我们这里没有传入参数进去)

call now():

2013-12-25

 

这个装饰器定义的时候,我们在里面定义了函数的参数,所以这里我们的装饰器是可以接收任何参数的调用,在wrapper()函数内,首先打印文字,然后就是调用原始函数now()了。

 

但是我们要是想调用装饰器里面的参数的话,我们外面还得再加一个嵌套函数

def log(txt):

    def decorator(func):

        def wrapper(*args,**kv):
           print 'call %s %s():' % (txt,func.__name__)

           return func(*args,**kv)

        return wrapper

    return decorator

@log('hello')

def now():
    print '2013-02-15'

 

我们现在调用函数的话

now()    现在相当于是执行了log('hello')(now)  然后复制给now变量,now = log('hello')(now)

输出的结果就是

hello now():

2013-02-15'

解析一下上面的语句:
首先执行log(‘hello’),返回的是decorator函数,就是上面的颜色荧光绿

再调用返回的函数decorator,参数func就是now()函数,返回值最终是wrapper函数,就是上面的鸭屎绿颜色

wrapper函数在调用自己定义的print 函数打印功能,返回return func(*args,**kv)

但是还有一种情况

我们返现now()函数__name__的时候输出的尽然是wrapper

这是为什么呢,我们看一下,我们上面定义的装饰器,我们看一下定义的derator函数,他的参数是now()函数,他返回的函数是wapper()函数,所以这里now.__name__输出的就是wrapper

这里detator函数的参数func(也就是要传过去的now()函数)没有把我们的参数(即now()函数)的__name__等其他属性没有复制到wrapper函数中,所以最终now.__name__返回的是wrapper,

所以这里我们需要把原始函数now()的__name__等其他属性给复制到wrapper函数中,这个就需要调用functools这个模块了



文章参考:
http://www.liaoxuefeng.com/wiki/001374738125095c955c1e6d8bb493182103fac9270762a000/001386819879946007bbf6ad052463ab18034f0254bf355000#0

老师最后留了一个作业还没有做,有时间做一下

推荐阅读