最近在学习Python,到装饰器这一部分,不知理解的是否正确
1 #coding:utf-8 2 3 #装饰器原理介绍和基本实现 4 5 #例子 6 ''' 7 说明: 8 1.假设在调用home()和move()函数前,需要先验证 9 2.但是不能修改home()和move()里面的代码 10 11 方法步骤: 12 1.设定一个新的验证函数login(),让home()和move()函数执行前,先执行login()函数 13 2.给login()方法传参,参数为tv函数的内存地址(tv函数不带"()",这样传入的就是内存地址而不会执行函数) 14 3.login()函数设定返回值,返回值为tv函数传入的内存地址(也就是tv) 15 4.用一个变量来接收login()函数返回的值(返回值为tv函数的内存地址) 16 5.接收login()函数的变量tv,加上括号"tv()",执行tv()函数 17 ''' 18
19 #用普通函数来实现以上要求 20 def login(func): #验证函数 21 print("passed user verification...") 22 print(func) 23 return func 24 25 def tv(name): #tv函数 26 print("Welcome 【%s】 to tv page"%name) 27 28 tv = login(tv) #login()函数传入tv()函数的内存地址(tv函数并不执行),在用一个变量tv来接收返回值 29 tv("eric") #此时tv变量值为tv()这个函数的内存地址,加上“()”来执行此函数 30 31
32 #用装饰器来实现以上要求 33 def login(func): 34 print("passed user verification...") 35 print(func) 36 return func #返回tv函数的内存地址 37 38 @login #@login == login(tv)#1.程序开始加载时,就会先执行login()函数,并把tv函数的内存地址做为参数传入login()函数 39 def tv(name): 40 print("Welcome 【%s】 to tv page"%name) 41 42 tv("eric") #2.调用tv函数,此时执行tv()函数 43 44
45 #上面的例子有一个问题,当程序执行到@login装饰器时会马上执行里面的方法,我们不希望这样,而是希望调用tv函数时才执行里面的方法 46 def login(func): #2.把login()函数载入内存中 47 def inner(arg): #4.arg == eric"; 48 print("passed user verification...") 49 func(arg) #5.func == tv函数的内存地址;加上"(arg)"就是调用tv()函数并传入参数"arg" 50 return inner 51 52 @login #1.程序开始加载时先执行login()函数,并把tv函数的内存地址做为参数传入login()函数 53 def tv(name): 54 print("Welcome 【%s】 to tv page"%name) 55 return 111 56 #tv = login(tv) 57 tv("eric") #3.这个tv是一个变量,值为login()函数的返回值,目前返回值为inner函数的内存地址,通过执行tv("eric")传入参数,相等于调用了inner("eric") 58
59 60 #函数调用时传多个参数 61 def login(func): 62 def inner(*args,**kwargs): #调用时多参数传参 63 print("passed user verification...") 64 func(*args,*kwargs) 65 return inner 66 67 @login 68 def tv(name,passwd=123): 69 print("Welcome 【%s】 to tv page your password is 【%s】"%(name,passwd)) 70 return 111 71 #tv = login(tv) 72 tv("eric",'123456') 73 74 75
76 77 ##实现带参数的装饰器 78 ''' 79 要求: 80 用一个可带参数的装饰器实现功能复用 81 1.再某个函数执行时(例如index()函数),需要在函数的前面和后面分别执行一个其它函数 82 2.假如有N个类似index(),需要怎么实现 83 ''' 84 106 #执行顺序
#1、执行Filter(before,after) #装饰器有参数(不会再把它下面的函数当做参数传入)
#2、outer #在装饰器嵌套的第二层outer函数,才会把Index内存对象函数当做参数传入
#3、Index = 新的Index #装饰器会返回一个函数内存对象,让装饰器下面的函数接收(Index()函数)
#4、Index("aa","bb") #接收装饰器返回的内存对象后,调用执行
85 def Before(request, kargs): 86 print('before') 87 88 def After(request, kargs): 89 print('after') 90 91 def Filter(before_func, after_func): 92 def outer(main_func): #2.在执行outer装饰器,传入Index函数的内存对象,并返回warpper函数的内存对象给Index变量 93 def wrapper(request, kargs): #4.request == "aa", kargs == "bb" 94 before_func(request, kargs) #5.before_func为Before函数的内存对象,调用并传参("aa","bb") 95 main_func(request, kargs) #6.main_func为Index函数的内存对象,调用并传参("aa","bb") 96 after_func(request, kargs) #7.after_func为After函数的内存对象,调用并传参("aa","bb") 97 return wrapper 98 return outer 99 100 @Filter(Before, After) #1.执行Filter装饰器(参数为Before, After两个函数内存对象),有参数的Filter装饰器不会再把Index的内存对象传入 101 def Index(request, kargs): 102 print('index') 103 104 Index("aa","bb") #3.Index变量接收warpper函数的内存对象,调用arpper函数并传参"("aa","bb")"
例子:
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 ##带参数的装饰器 2 ''' 3 说明: 4 1.假设在调用home()和move()函数前,需要先验证 5 2.但是不能修改home()和move()里面的代码 6 7 方法步骤: 8 1.设定一个新的验证函数login(),让home()和move()函数执行前,先执行login()函数 9 2.给login()方法传参,参数为tv函数的内存地址(tv函数不带"()",这样传入的就是内存地址而不会执行函数) 10 3.login()函数设定返回值,返回值为tv函数传入的内存地址(也就是tv) 11 4.用一个变量来接收login()函数返回的值(返回值为tv函数的内存地址) 12 5.接收login()函数的变量tv,加上括号"tv()",执行tv()函数 13 ''' 14 15 16 def Before(request, kargs): 17 print('before') 18 19 def After(request, kargs): 20 print('after') 21 22 def Filter(before_func, after_func): 23 def outer(main_func): 24 def wrapper(request, kargs): 25 before_func(request, kargs) 26 main_func(request, kargs) 27 after_func(request, kargs) 28 return wrapper 29 return outer 30 31 @Filter(Before, After) 32 def Index(request, kargs): 33 print('index') 34 35 Index("aa","bb")