装饰器:原函数基础 ------> 动态添加功能


一、不带参数的decorator

#decorator封装

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


#此函数一定要放在 def log(func): 之后

@log
def now():
print "haha"


now()


log(now())


print "now_name:%s"%now.__name__


简单的图解:(待以后深入理解后再详细补)


二、带参数的docurator

#!/usr/bin/python

#docurator封装

def log(text):
def decorator(func):
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator


@log('execute')
def now():
print "haha"


print "now_name:%s"%now.__name__


now()


print log('execute')
print log(now)
print log('execute')(now)


三、完整的decorator的写法:Python内置的functools.wraps

import functools #导入functools模块

def log(text):
def decorator(func):
@functools.wraps(func)
def wrapper(*args, **kw):
print('%s %s():' % (text, func.__name__))
return func(*args, **kw)
return wrapper
return decorator

@log('execute')
def now():
print "haha"

print "now_name:%s"%now.__name__

now()

print log('execute')
print log(now)
print log('execute')(now)



--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

日期:2018/8/18

--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

补充:

多个装饰器的执行顺序是无序的,但执行过程是有序的。

装饰器执行过程是:遇到外接函数就跳转到另一个装饰器中执行,若再另一个装饰器中遇到同样的外接函数,则继续执行


证明1:多个装饰器的执行顺序是无序的

#!/usr/bin/python#-*-coding:utf-8-*-importtimedefextend(func):defwrapper(*args,**kwargs):print"BeginAAAAAA"func(*args,**kwargs)print("A:%s"%(func.__name__))print(reduce(lambdax,y:x+y,args),kwargs)print"EndAAAAA"returnwrapperdefextend1(func):defwrapper(*args,**kwargs):print"BeginBBBBB"func(*args,**kwargs)print("B:%s"%(func.__name__))print(map(lambdax:x*2,args),kwargs)print"EndBBBBB"returnwrapper@extend@extend1defget_time1(*args,**kwargs):begin_time=time.time()forninrange(3,4):time.sleep(1)end_time=time.time()print("run%d"%(end_time-begin_time))#print(reduce(lambdax,y:x+y,args),kwargs)if__name__=="__main__":get_time1(1,2,3,4,5,6,ma=1,du=2)

执行结果:先从第一个装饰器标志@extend开始

BeginAAAAAABeginBBBBBrun1B:get_time1([2,4,6,8,10,12],{'du':2,'ma':1})EndBBBBBA:wrapper(21,{'du':2,'ma':1})EndAAAAA


另一个例子:

#!/usr/bin/python#-*-coding:utf-8-*-defdec1(func):print("1111")defwrapper(*args,**kwargs):print("2222")func()print("3333")returnwrapperdefdec2(func):print("aaaa")defwrapper(*args,**kwargs):print("bbbb")func()print("cccc")returnwrapper@dec1@dec2deftest():print("testtest")test()

运行结果:从第二个装饰器标志@dec2开始

aaaa11112222bbbbtesttestcccc3333


通过比较,多个解释器的执行顺序是无序的。若大家觉得证明不够严谨,可自己多添几个试试。


证明2:装饰器的执行过程是有序的

图1:


图2:




没看懂?没关系,进行步骤解析:



-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

2018/8/20

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

补充:一个讲的很好的BLOG: https://blog.csdn.net/xiangxianghehe/article/details/77170585