装饰器:开放封闭原则,为一个函数加上新的功能,不改变原函数,不改变调用方式
def fun2(wtf): def fun3(): print('i am pythoner!!! ') wtf() return fun3 @fun2 def fun1(): print('this is fun1') fun1() 输出:
i am pythoner!!!
this is fun1
1 def fun2(wtf): 2 def fun3(*args, **kwargs): 3 print('i am pythoner!!! ') 4 wtf(*args, **kwargs) 5 return fun3 #这里不是fun3()是因为:return作用在于函数赋值,即让fun3指向fun1的函数内存地址 6 7 @fun2 # @fun2 当于fun1 = fun2(fun1) ,把下面的函数传递到装饰器函数里面,相当于 fun1 = fun2(fun1) = fun3(用return令fun1=fun3), 后面再执行fun1() , 相当于执行fun3() 8 def fun1(arg, arg2): 9 print('this is fun1: %s %d' % (arg, arg2))10 fun1('tom', 55) #注意此处fun1()调用的实际是fun3(),而不是原来的fun1()了 注意:只要函数应用装饰器,函数就被重新定义,重新定义为:装饰器的内层函数
def runtime(func): def warpper(): start_time = time.time() func() end_time = time.time() print 'run time is %s' % (end_time-start_time) return warpper @runtime def test1(): time.sleep(3) print 'in the test1' test1() 带参数的装饰器举例:
1 def outer(func): 2 def inner(a, b): 3 print('heihei') 4 r = func(a, b) #func即index函数,即inner函数 5 return r 6 return inner 7 8 9 @outer # index = outer(index) = inner10 def index(a1, a2):11 print('----------')12 return a1 + a213 14 print(index(1, 2))15 16 输出:17 heihei18 ---------- 19 3 @outer 作用 1. 执行outer函数,将index作为参数传递 2. 将outer的返回值,重新赋值给index 3. 执行index函数时不再是原来的index函数,而是执行装饰器中的inner函数(由装饰器中的return赋值使index=inner)
带N个参数的装饰器: 应用场景: 当一个装饰器装饰多个函数时,而这些函数的参数个数都不相同时。 原理:
1 #原理: 2 def f1(*args, **kwargs): 3 print(args) 4 print(kwargs) 5 6 f1(1, 2, 3, 4, M1='123') 7 输出: 8 (1, 2, 3, 4) 9 { 'M1': '123'}10 11 dic = { 'a': 2, 'b': 23333}12 tup = (1, 2, 3)13 f1(*tup, **dic)14 15 输出:16 (1, 2, 3)17 { 'a': 2, 'b': 23333}
举例:
1 def outer(func): 2 def inner(*args, **kwargs): 3 print('into inner') 4 print('the arg is :', *args, **kwargs) 5 r = func(*args, **kwargs) 6 return r 7 return inner 8 9 @outer # index = outer(index) = inner10 def index(a1, a2):11 print('----------')12 return a1 + a213 14 print(index(1, 2))15 16 @outer # f1 = outer(f1) = inner17 def f1(a1):18 print('++++++++++++++++++++++++++')19 return a1 * a120 print(f1(2))21 22 #输出:23 into inner24 the arg is : 1 225 ----------26 327 into inner28 the arg is : 229 ++++++++++++++++++++++++++30 4
多个装饰器装饰同一个函数:
1 def outer(func): #func等同于outer2中的inner2 2 def inner(*args, **kwargs): 3 print('first decorate-------------') 4 print('the arg is :', *args, **kwargs) 5 r = func(*args, **kwargs) #func等于outer2中的inner2,r值为inner2中的 return r 6 print('first decorate-------------') 7 return r # r的值最终返回给index 8 return inner 9 10 11 def outer2(func): #func等于index12 def inner2(*args, **kwargs): #inner2等同于于outer2+被outer2装饰的index函数13 print('second decorate-----------')14 r = func(*args, **kwargs) #func等于index,r值为index的return a1 + a215 print('second decorate------------')16 return r #r为inner2的返回值,返回给outer中的func函数17 return inner218 19 20 @outer # outer(inner2) = inner, 作用:将outer2装饰的index,即inner2当作参数传递到第一个装饰器中outer中21 @outer2 # index = outer2(index) = inner2 22 def index(a1, a2):23 print('ori func----------')24 return a1 + a225 26 print(index(1, 2))27 28 输出:29 first decorate-------------30 the arg is : 1 231 second decorate-----------32 ori func----------33 second decorate------------34 first decorate-------------35 3 执行顺序说明: 当运行index(1, 2)时, 1.执行第一个装饰器outer中的inner函数 2.由1步中的inner函数中的func函数,执行outer2中的inner2函数 3.执行outer2中inner2中的func函数,即执行最初需要装饰的index函数 4.index的返回值返回给它的调用者,即inner2中的func函数 5。inner2的返回值返回给它的调用者,即inner中的func函数 6.将r返回给index函数
自身带参数的装饰器
例1:
1 user_list=[ 2 { 'name':'alex','passwd':'123'}, 3 { 'name':'linhaifeng','passwd':'123'}, 4 { 'name':'wupeiqi','passwd':'123'}, 5 { 'name':'yuanhao','passwd':'123'}, 6 ] 7 current_dic={ 'username':None,'login':False} 8 9 def auth(auth_type='filedb'):10 def auth_func(func):11 def wrapper(*args,**kwargs):12 print('认证类型是',auth_type)13 if auth_type == 'filedb':14 if current_dic['username'] and current_dic['login']:15 res = func(*args, **kwargs)16 return res17 username=input('用户名:').strip()18 passwd=input('密码:').strip()19 for user_dic in user_list:20 if username == user_dic['name'] and passwd == user_dic['passwd']:21 current_dic['username']=username22 current_dic['login']=True23 res = func(*args, **kwargs)24 return res25 else:26 print('用户名或者密码错误')27 elif auth_type == 'ldap':28 print('鬼才特么会玩')29 res = func(*args, **kwargs)30 return res31 else:32 print('鬼才知道你用的什么认证方式')33 res = func(*args, **kwargs)34 return res35 36 return wrapper37 return auth_func38 39 @auth(auth_type='filedb') #auth_func=auth(auth_type='filedb')-->@auth_func 附加了一个auth_type --->index=auth_func(index)40 def index():41 print('欢迎来到京东主页')42 43 @auth(auth_type='ldap')44 def home(name):45 print('欢迎回家%s' %name)46 #47 @auth(auth_type='sssssss')48 def shopping_car(name):49 print('%s的购物车里有[%s,%s,%s]' %(name,'奶茶','妹妹','娃娃'))50 51 # print('before-->',current_dic)52 # index()53 # print('after--->',current_dic)54 # home('产品经理')55 shopping_car('产品经理')
例2:
1 # !/usr/bin/env python 2 # coding:utf-8 3 4 5 def before(request, kargs): 6 print('before') 7 8 9 def after(request, kargs):10 print('after')11 12 13 def Filter(before_func, after_func):14 def outer(main_func):15 def wrapper(request, kargs):16 17 before_result = before_func(request, kargs)18 if before_result:19 return before_result20 21 main_result = main_func(request, kargs)22 if main_result:23 return main_result24 25 after_result = after_func(request, kargs)26 if after_result:27 return after_result28 29 return wrapper30 31 return outer32 33 # outer = Filter(before, after) ---> 相当于@outer附带参数(before, after) 相当于执行 ==> index = outer(index)34 @Filter(before, after)35 def index(request, kargs):36 print('index')37 38 index(1,2)39 40 41 # 带参数的装饰器:利用装饰器的最外层函数传参
装饰器------------自己的理解(持续更新)
1 def fun2(wtf): 2 def fun3(): 3 print('i am pythoner!!! ') 4 wtf() 5 return fun3 6 7 8 @fun2 9 def fun1():10 print('this is fun1')11 fun1()12 13 输出:14 i am pythoner!!! 15 this is fun116 17 18 19 fun2只是个桥梁:20 0.把要装饰的函数接收进来,嵌套进包含新功能的函数(这个函数同时包含原函数功能)21 1.让fun1和fun3内存地址相同22 23 24 目的:装饰后在fun1()执行前后再执行一些其他的动作25 26 27 28 def outer(func): #29 def inner(a, b): # 2 a:1 b:230 print('heihei') # 331 r = func(a, b) # func即index函数,即inner函数 # 432 return r # 如果index有返回值,这里要加上return返回index的返回值 # 733 return inner # 作用:让index和inner内存地址相同34 35 36 @outer # index = outer(index) = inner37 def index(a1, a2):38 print('----------') # 539 return a1 + a2 # 640 41 42 print(index(1, 2)) # 偷梁换柱,相当于直接执行包含原函数功能的函数inner(1, 2) # 1
def write_log(func): def wrapper(a, b): print 'log --------------' return func(a, b) return wrapper# @write_logdef bar(a,b): return a + bprint write_log(bar)(1, 3)# write_log(bar) 等于 wrapper# write_log(bar)(1, 3) 等于 wrapper(1, 3)#输出:log --------------4