美文网首页
【python】装饰器

【python】装饰器

作者: 我写的BUG代码少 | 来源:发表于2020-04-23 10:12 被阅读0次

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(+基本装饰器的使用)

  • 【装饰器的作用】不修改函数的调用方式 func(), 还在原来的函数前后添加功能【使用闭包函数
  • timmer()就是一个装饰器函数,只是对一个函数 有一些装饰作用
#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(+语法糖:装饰器简便使用)

  • 语法糖:在被装饰的函数上加@装饰器的名字==(3.实际调用中注释的那句话
#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.装饰器进阶

  • EG:调用被装饰函数实际调用的是装饰函数中的内部函数
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 带参数的装饰器

  • 通过只要改flag,可以控制多个函数的装饰器
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
哈哈哈

开发原则:开放封闭原则

  • 开放:对扩展是开放的
  • 封闭:对修改是封闭的(不能修改封板的代码)

相关文章

  • 装饰器模式

    介绍 在python装饰器学习 这篇文章中,介绍了python 中的装饰器,python内置了对装饰器的支持。面向...

  • python中的装饰器

    python装饰器详解 Python装饰器学习(九步入门) 装饰器(decorator) 就是一个包装机(wrap...

  • [译] Python装饰器Part II:装饰器参数

    这是Python装饰器讲解的第二部分,上一篇:Python装饰器Part I:装饰器简介 回顾:不带参数的装饰器 ...

  • Python中的装饰器

    Python中的装饰器 不带参数的装饰器 带参数的装饰器 类装饰器 functools.wraps 使用装饰器极大...

  • Python进阶——面向对象

    1. Python中的@property   @property是python自带的装饰器,装饰器(decorat...

  • Python 装饰器填坑指南 | 最常见的报错信息、原因和解决方

    Python 装饰器简介装饰器(Decorator)是 Python 非常实用的一个语法糖功能。装饰器本质是一种返...

  • Python装饰器

    Python装饰器 一、函数装饰器 1.无参装饰器 示例:日志记录装饰器 2.带参装饰器 示例: 二、类装饰器 示例:

  • python3基础---详解装饰器

    1、装饰器原理 2、装饰器语法 3、装饰器执行的时间 装饰器在Python解释器执行的时候,就会进行自动装饰,并不...

  • 2019-05-26python装饰器到底是什么?

    装饰器例子 参考语法 装饰器是什么?个人理解,装饰器,是python中一种写法的定义。他仍然符合python的基本...

  • 2018-07-18

    Python装饰器 装饰,顾名思义,是用来打扮什么东西的。Python装饰...

网友评论

      本文标题:【python】装饰器

      本文链接:https://www.haomeiwen.com/subject/glkoihtx.html