【python】装饰器

2020-04-23  本文已影响0人  我写的BUG代码少

B站视频链接

目录

装饰器

import time
time.sleep(10)  #让程序在执行到这个位置的时候停一会儿(10s
time.time()     #获取当前时间:从1970.1.1到现在过了多少秒

1.Eg.计算函数运行时间

原始代码

    ```python
    def func():
        start=time.time()
        
        print('这段代码跑完了') 
        time.sleep(0.01) #让程序执行到这个位置的时候停一会(因为程序执行时间太少)
        
        end=time.time()
        print(end-start)
    
    func()
    ```

修改v1

    ```python
    #0.
    import time
    
    #1.计时器
    def timmer(f):
        start=time.time()
        f()   #调用func(),以参数的形式传进来
        end=time.time()
        print(end-start)
    
    #2.自定义的函数    
    def func():
        time.sleep(0.01)
        print('这段代码跑完了')
    
    #3.实际调用
    timmer(func)
    ```

修改v2(+基本装饰器的使用)

#0.
import time

#1.自定义的函数   
def func():             #1.
  time.sleep(0.01)                 #10.
  print('这段代码跑完了')           #11.

#2.计时器
def timmer(f): #装饰器函数   #2.  #3.2 f>>>func()刚刚传来的内存地址
  def inner():             #4.定义inner()
      start = time.time()       #8.
      f()   #被装饰的函数      #9.f()实际调用func()(以参数的形式传进来)
      end = time.time()             #12.
      print(end-start)            #13.finnal
  return inner             #5.返回inner给3.1的func 【inner作为timmer()的返回值==func
  

#3.实际调用
func = timmer(func)  #3.1调用timmer(),将1.的func()的内存地址传给timmer()  #6.
func()   #7.实际执行的是inner()

修改v3(+语法糖:装饰器简便使用)

#0.
import time

#1.计时器
def timmer(f): #装饰器函数   
   def inner():          
       start = time.time()       
       f()   #被装饰的函数      
       end = time.time()        
       print(end-start)         
   return inner              

#2.自定义的函数   
@timmer #语法糖  #执行3.实际调用
def func():             
   time.sleep(0.01)                 
   print('这段代码跑完了')           
  
#func = timmer(func)  #3.实际调用:替换为 @timmer
func()   

修改v4(+函数有返回值)


#0.
import time

#1.计时器
def timmer(f):   #1.定义
   def inner():         #4.执行,定义
       start = time.time()     #8.
       res = f()   #*** #9.调用func(); #func()的返回值'aaa'>>>res
       end = time.time()      #13.  
       print(end-start)       #14.
       return res  #*** 15.返回被装饰函数f()的执行结果;res作为inner()的返回值,inner()==res=='aaa'
   return inner       #5.timmer()==inner       

#2.自定义的函数   
@timmer                    #3.执行timmer()
def func():             #2.定义
   time.sleep(0.01)        #10.         
   print('这段代码跑完了')   #11.
   return 'aaa'  #***        #12.'aaa'==func()

#func=timmer(func)  #(3) #6.inner>>>func
res = func()  #7.实际调用的是inner()//原始inner()无返回值;需获取inner的返回值
print(res)   #16.res=='aaa'

>>>
这段代码跑完了
0.013279199600219727
aaa

修改v5(+传一个参数)

#0.
import time

#1.计时器
def timmer(f):   #1.定义
   def inner(a):         #4.执行,定义
       start = time.time()     #8.
       res = f(a)   #*** #9.调用func(); #func()的返回值'aaa'>>>res
       end = time.time()      #13.  
       print(end-start)       #14.
       return res  #*** 15.返回被装饰函数f()的执行结果;res作为inner()的返回值,inner()==res=='aaa'
   return inner       #5.timmer()==inner       

#2.自定义的函数   
@timmer                    #3.执行timmer()
def func(a):             #2.定义
   time.sleep(0.01)        #10.         
   print('这段代码跑完了',a)   #11.
   return 'aaa'  #***        #12.'aaa'==func()

#func=timmer(func)  #(3) #6.inner>>>func
res = func(1)  #7.实际调用的是inner()//原始inner()无返回值;需获取inner的返回值
print(res)   #16.res=='aaa'

>>>
这段代码跑完了 1
0.01414799690246582
aaa

修改v6(+万能动态参数,任意传参)

#0.
import time

#1.计时器
def timmer(f):   
   def inner(*args,**kwargs):      #(1,2)/(1)    
       start = time.time()     
       res = f(*args,**kwargs)     #f(1,2)
       end = time.time()      
       print(end-start)       
       return res 
   return inner           

#2.自定义的函数1   
@timmer                   
def func(a,b):             
   time.sleep(0.01)                
   print('这段代码跑完了',a,b)   
   return 'aaa' 

#2.自定义的函数2  
@timmer                   
def func1(a):            
   time.sleep(0.01)                 
   print('这段代码跑完了',a)   
   return 'aaa'  

#func=timmer(func) 
res = func(1,2) 
res = func(1,b=2)
print(res)   

2.装饰器定式

def wrapper(f):   #装饰器函数,f是被装饰函数
   def inner(*args,**kwargs):  #定义内部函数,名字和wrapper的返回值一致    
       ''' 在被装饰函数之前要做的事'''
       res = f(*args,**kwargs)  #内部函数参数要原封不动传给被装饰函数            
       ''' 在被装饰函数之后要做的事'''
       return res  #返回被装饰函数
   return inner #将内部函数返回给装饰器函数         

@wrapper                   
def func(a,b):             
   time.sleep(0.01)                
   print('这段代码跑完了',a,b)   
   return 'aaa' 
res = func(1,2) 
print(res)  

3.装饰器进阶

def wrapper(func):   #func = holiday 
   def inner(*args,**kwargs):      
       print('在被装饰函数之前要做的事')
       res = func(*args,**kwargs)         
       print('在被装饰函数之后要做的事')
       return res 
   return inner      

@wrapper                   
def holiday(day):                          
   print('全天放假%s天'%day)   
   return '好开心' 

res = holiday(3)  #inner()
print(holiday.__name__)  #.__name__ 查看函数所属地址的函数名
#holiday的内存地址指向inner,因此打印的是inner的名字
>>>
在被装饰函数之前要做的事
全天放假3天
在被装饰函数之后要做的事
inner ***

3.1 functools.wraps

from functools import wraps #***
def wrapper(func):   #func = holiday 
   @wraps(func)      #***给inner函数装饰
   def inner(*args,**kwargs):      
       print('在被装饰函数之前要做的事')
       res = func(*args,**kwargs)         
       print('在被装饰函数之后要做的事')
       return res 
   return inner      

@wrapper                   
def holiday(day):                          
   print('全天放假%s天'%day)   
   return '好开心' 

res = holiday(3)  #inner()
print(holiday.__name__)  #.__name__ 查看函数所属地址的函数名

>>>
在被装饰函数之前要做的事
全天放假3天
在被装饰函数之后要做的事
holiday ***

3.2 带参数的装饰器

import time
FLAGE = True
def timmer_out(flag):
   def timmer(func):  
      def inner(*args,**kwargs):  
         if flag == True:    
            start = time.time()
            res = func(*args,**kwargs)         
            end = time.time()
            print(end-start)
            return res 
         else:
            res = func(*args,**kwargs)      
            return res    
      return inner      
   return timmer
#timmer = timmer_out(FLAGE) 省略了这一步
@timmer_out(FLAGE)    #两步:先调timmer_out(),返回值timmer>>>timmer_out(flag); @timmer== wahaha=timmer(wahaha)     
def wahaha():                          
    time.sleep(0.1)
    print('wahahhahhahah')

@timmer_out(FLAGE)    
def erguotou():
    time.sleep(0.1)
    print('toutoutoutouto')

wahaha()
erguotou()

3.3 多个装饰器装饰同一个函数

双层装饰器

def wrapper1(func):
    def inner1():
        print('wrapper1, before func')
        func()
        print('wrapper1, after func')
    return inner1

def wrapper2(func):
    def inner2():
        print('wrapper2, before func')
        func()
        print('wrapper2, after func')
    return inner2
   
@wrapper2
@wrapper1
def f():
    print('in f')

f()

>>>
wrapper2, before func
wrapper1, before func
in f
wrapper1, after func
wrapper2, after func

三层装饰器+返回值

def wrapper1(func):  
    def inner1():
        print('wrapper1, before func')
        ret = func()  
        print('wrapper1, after func')
        return ret
    return inner1

def wrapper2(func): 
    def inner2():
        print('wrapper2, before func')
        ret = func()  
        print('wrapper2, after func')
        return ret
    return inner2
   
def wrapper3(func): 
    def inner3():
        print('wrapper3, before func')
        ret = func()  
        print('wrapper3, after func')
        return ret
    return inner3

@wrapper3
@wrapper2  
@wrapper1  
def f():
    print('in f')
    return '哈哈哈'

print(f())  

>>>
wrapper3, before func
wrapper2, before func
wrapper1, before func
in f
wrapper1, after func
wrapper2, after func
wrapper3, after func
哈哈哈

开发原则:开放封闭原则

上一篇 下一篇

猜你喜欢

热点阅读