首页 > 代码库 > 装饰器

装饰器

最近在学习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\nyour 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")" 105

 

装饰器