装饰器:(语法糖)python
1 嵌套函数 在一个函数的函数体内,用def声明一个新函数 2 def foo(): 3 print('in the foo.') 4 def bar(): 5 print('in the bar.') 6 bar() #要调用bar须要在在函数体内调用,相似局部变量 7 foo()
装饰器例子:仅针对注释的几段,对其进行排序,以下红字app
1 import time #python的debug都是先读取最外层框架(最外层没有缩进),最外层中若是涉及到调用,再接着运行调用内容。 第一步 2 3 def timer(func): #当读取到 @timer的时候,至关于运行 test1 = timer(test1),因此会返回来读取 warpper 第三步 4 def warpper(*args,**kwargs): 5 start_time = time.time() 6 func(*args,**kwargs) #此时才是真正意义上运行 test1函数 第六步
return func(*args,**kwargs) #保证fun()返回值也不变 7 stop_time = time.time() 8 print('in the test1() %s'%(stop_time-start_time)) 9 return warpper #把test1看成实参传递给 timer,timer(test1),此时返回的是 函数warpper的内存地址 第四步 10 11 #而后此时运行到 python里的语法【@timer】 12 @timer #至关于 test1 = timer(test1),返回warpper的内存地址,此时若是运行 test1(),至关于 warpper(),warpper就开始执行其函数体内的语句 第二步 13 def test1(): 14 time.sleep(1) 15 print('in the test1')
return ‘from test1’ 16 test1() #此时运行的 test1()已经不是直接运行 test1函数了,是通过@timer,转换成运行 warpper()了 第五步
装饰器进阶版,装饰器自己带参数框架
1 user = 'gkx' 2 pass_1 = '123' 3 def decorator(auth_type): 4 print("auth type",auth_type) 5 def outer_warpper(func): 6 def warpper(*args,**kwargs): 7 if auth_type == 'local': 8 username = input("id") 9 password = input("password") 10 if username == user and password == pass_1: 11 print('\033[32;1mwelcome\033[0m') 12 res = func(*args,**kwargs) 13 print("after decorator") 14 return res 15 else: 16 print('\033[31;1mwrong info\033[0m') 17 elif auth_type == 'ldap': 18 print('我不会') 19 return warpper 20 return outer_warpper #当访问到这里的返回值时候,会继续执行 warpper,而后执行逻辑就和上面提到的timer同样了 21 22 23 24 @decorator(auth_type='local') #这里分红两部分看,第一部分是 调用decorator(auth_type = 'local'),此时返回outer_wrapper的内存地址
#在第一部分的基础上,此时加上@,变成了 @outer_wrapper,至关于 homepage = outer_wrapper(wrapper),再返回了wrapper的内存地址
25 def homepage():
26 print('home page')
27 return 'from home'
29 @decorator(auth_type='ldap') 30 def bbs(): 31 print('in bbs') 32 33 print(homepage()) 34 bbs()
装饰器三个重要补充:ide
#一共有三个 # 第一个 from functools import wraps def outer(func): @wraps(func) #wraps模块 def inner(*args,**kwargs): print('装饰前') ret = func(*args,**kwargs) print('装饰后') return ret return inner @outer def holiday(day): ''' :param day: days of vacation :return: ''' print("放假%s"%day) return '好开心' print(holiday.__name__) #import wraps后此时打印holiday函数名,不然是 inner函数名 print(holiday.__doc__) ret = holiday(3) print(ret) # 第二个,当装饰器带参数 import time FLAG = False def out_timmer(flag): def timmer(func): def inner(*args,**kwargs): if flag: start = time.time() ret = func() end = time.time() print(start-end) return ret else: ret = func() return ret return inner return timmer @out_timmer(FLAG) #能够当作两部 1, timmer = out_timmer(FLAG) 2, @timmer def shop1(): time.sleep(0.01) print('buy first thing') @out_timmer(FLAG) def shop2(): time.sleep(0.01) print('buy second thing') shop1() shop2() #第三个 函数被多个装饰器调用 def wrapper1(func): #func-----> f def inner1(): print('wrapper1,befor func') ret = func() print('wrapper1,after func') #这一句运行完,可是inner2还没结束,要返回inner2继续运行【print('wrapper2,after func')】 return ret return inner1 def wrapper2(func): #func-----> inner1 inner1传给了wrapper2 def inner2(): print('wrapper2,befor func') #运行完这一句,下一句运行inner1,故返回到wrapper1继续运行 ret = func() #inner1 print('wrapper2,after func') return ret return inner2 @wrapper2 #wrapper1 执行完后,执行wrapper2 可是此时传入的不是f,是 inner1,至关于 wrapper(inner1) == inner2 而后继续运行warpper2 @wrapper1 #先执行到这里,由于语法糖要找离它最近的函数。wrapper2没找到,故往下运行。此时函数 f传给wrapper1 至关于 f = wrapper1(f) 即为 inner1 def f(): print('in the f') f() #--------->>调用inner2