• 装饰器


     装饰器概念

    1 什么是装饰器
    器=>工具
    装饰=>指的是为被装饰对象添加新功能

    装饰器本身可以是任意可调用的对象=>函数
    被装饰的对象也可以是任意可调用的对象=>函数

    目标:写一个函数来为另外一个函数添加新功能
    2 为何要用装饰器
    开放封闭原则: 软件一旦上线就应该对修改封闭,对扩展开放
    对修改封闭:
    1. 不能修改功能的源代码
    2. 也不能修改功能的调用方式

    对扩展开发:
    可以为原有的功能添加新的功能
    装饰器就是要在不修改功能源代码以及调用方式的前提下为原功能添加额外新的功能
    3 如何用装饰器

    装饰器代码

    #统计不同程序的运行时间
    import time
    def index():
        print('welcome to index page')
        time.sleep(3)
    #统计谁的时间,传谁
    def outter(func):
        # func=最原始那个index的内存地址
        def wrapper():
            start = time.time()
            func()  # 最原始那个index的内存地址()
            stop = time.time()
            print('run time is %s' % (stop - start))
        return wrapper
    #下面一行的目的是偷梁换柱
    index = outter(index)  # index=outter(最原始那个index的内地址) #index=wrapper函数的内地址
                           #为了不改变调用方式,将变量名定义为index
    index()                #调用wraper(),index的地址已经变成wrapper的地址

     装饰器修正1:

       #需要得到被装饰函数的返回值
    1
    import time 2 3 def index(): 4 print('welcome to index page') 5 time.sleep(3) 6 return 123 7 8 =================================== 9 def outter(func): 10 # func=最原始那个index的内存地址 11 def wrapper(): 12 start=time.time() 13 res=func() # 最原始那个index的内存地址() 14 stop=time.time() 15 print('run time is %s' %(stop-start)) 16 return res  #res是index()的返回值 17 return wrapper 18 19 index=outter(index) #index=outter(最原始那个index的内地址) #index=wrapper函数的内地址 20 =================================== 21 22 res=index() #res=wraper()实际调用 23 print(res) #打原始index()的返回值

    装饰器修正2:

     1 #当对多个方法进行装饰时,需要传入不同参数
     2 import time
     3 
     4 def index():
     5     print('welcome to index page')
     6     time.sleep(3)
     7     return 123
     8 
     9 def home(name):
    10     print('welcome %s to home page' %name)
    11     time.sleep(1)
    12 
    13 #==================================
    14 def outter(func):
    15     # func=最原始那个home的内地址
    16     def wrapper(*args,**kwargs):#可以传入任意参数,此处只是作为参数的中转,然后给传给func()
    17         start=time.time()
    18         res=func(*args,**kwargs)
    19         stop=time.time()
    20         print('run time is %s' %(stop-start))
    21         return res
    22     return wrapper
    23 
    24 index=outter(index) #index=outter(最原始那个index的内地址) #index=wrapper函数的内地址
    25 home=outter(home) #index=outter(最原始那个home的内地址) #home=wrapper函数的内地址
    26 #===================================
    27 
    28 home('egon') #wrapper('egon')
    29 index() #wrapper()

     装饰器的语法糖:

    @装饰器的名字:要在被装饰对象正上方单独一行写上
    @timmer----->相当于func=timmer(func)括号内func-->为最原始的那个要被修饰的函数的内存地址)
     1 from functools import wraps#引用外部工具包来自动显示被装饰函数的方法名以及函数注释
     2 
     3 import time
     4 def timmer(func): # func=最原始那个home的内地址
     5     @wraps(func)
     6     def wrapper(*args,**kwargs):
     7         start=time.time()
     8         res=func(*args,**kwargs)
     9         stop=time.time()
    10         print('run time is %s' %(stop-start))
    11         return res
    12     return wrapper
    13 
    14 @timmer  #index=timmer(index) #index=timmer(最原始那个index内存地址) #index=wrapper函数的内存地址
    15 def index():
    16     """这是index功能"""
    17     print('welcome to index page')
    18     time.sleep(3)
    19     return 123
    20 
    21 @timmer  #home=timmer(home) #home=timmer(最原始那个home内存地址) #home=wrapper函数的内存地址
    22 def home(name): 
    23   """这是home功能"""
    24   print('welcome %s to home page' %name)
    25   time.sleep(1)
    26
    27 print(help(index))  #打印函数注释
    28 print(index.__name__) #打印函数名

     无参装饰器与有参装饰器(核心都是偷梁换柱为wrapper函数):

    无参装饰器(双层闭包函数):

    #无参装饰器的模板
    def outter(func):
        def wrapper(*args,**kwargs):
            res=func(*args,**kwargs)
            return res
        return wrapper

    无参装饰器:

     1 #登录状态验证,账户验证
     2 import time
     3 
     4 user_info={'current_user':None}#定义初始用户状态
     5 
     6 def auth(func):
     7     def wrapper(*args,**kwargs):
     8         if user_info['current_user'] is not None:#说明已经登录了
     9             res=func(*args,**kwargs)
    10             return res
    11         inp_user=input('username>>>: ').strip()
    12         inp_pwd=input('password>>>: ').strip()
    13         if inp_user == 'egon' and inp_pwd == '123':
    14             # 记录登录状态
    15             user_info['current_user']=inp_user
    16 
    17             print('login successful')
    18             res=func(*args,**kwargs)
    19             return res
    20         else:
    21             print('user or password error')
    22     return wrapper
    23 
    24 @auth
    25 def index():
    26     """这是index功能"""
    27     print('welcome to index page')
    28     time.sleep(2)
    29     return 123
    30 
    31 @auth
    32 def home(name):
    33     """这是home功能"""
    34     print('welcome %s to home page' %name)
    35     time.sleep(1)
    36 
    37 index()
    38 home('egon')

     有参装饰器(三层闭包函数,第三层用来传值

    #有参装饰器模板
    def outter2(xxx,yyy):
        def outter(func):    #被装饰函数名,不能加参数
            def wrapper(*args,**kwargs):#只是作为参数中转,不可加参数
                res=func(*args,**kwargs)
                print(xxx)  #要引用外部参数,只能通过外部函数传
                print(yyy)
                return res
            return wrapper
        return outter

     有参装饰器:

     1 #判断数据来源,根据不同来源做不同操作
     2 import time
     3 
     4 user_info={'current_user':None}
     5 
     6 def auth2(engine='file'):
     7     def auth(func):
     8         def wrapper(*args,**kwargs):
     9             if user_info['current_user'] is not None:
    10                 res=func(*args,**kwargs)
    11                 return res
    12             inp_user=input('username>>>: ').strip()
    13             inp_pwd=input('password>>>: ').strip()
    14 
    15             if engine == 'file':
    16                 print('基于文件的认证')
    17                 if inp_user == 'egon' and inp_pwd == '123':
    18                     # 记录登录状态
    19                     user_info['current_user']=inp_user
    20 
    21                     print('login successful')
    22                     res=func(*args,**kwargs)
    23                     return res
    24                 else:
    25                     print('user or password error')
    26             elif engine == 'mysql':
    27                 print('基于mysql数据的认证')
    28             elif engine == 'ldap':
    29                 print('基于ldap的认证')
    30             else:
    31                 print('无法识别认证源')
    32         return wrapper
    33     return auth
    34 
    35 @auth2(engine='mysql') # @auth ===> index=auth(最原始那个index的内存地址)===》index=wrapper
    36 def index():
    37     """这是index功能"""
    38     print('welcome to index page')
    39     time.sleep(2)
    40     return 123
    41 
    42 @auth2(engine='file')
    43 def home(name):
    44     """这是home功能"""
    45     print('welcome %s to home page' %name)
    46     time.sleep(1)
    47 
    48 index()     #wrapper()
    49 home('egon')#wrapper('egon')

     装饰器叠加:

    加载装饰器就是将原函数名偷梁换柱成了装饰器最内层那个wrapper函数
    在加载完毕后,调用原函数其实就是在调用wrapper函数

    当一个被装饰的对象同时叠加多个装饰器时
      装饰器的加载顺序是:自下而上
      装饰器内wrapper函数的执行顺序是:自上而下

     1 import time
     2 
     3 def timmer(func): #func=wrapper2的内存地址
     4     def wrapper1(*args, **kwargs):
     5         print('==================>wrapper1运行了')
     6         start=time.time()
     7         res = func(*args, **kwargs) #===================>跳到wrapper2去执行了,
     8         stop=time.time()
     9         print('run time is %s' %(stop - start))
    10         return res
    11     return wrapper1
    12 
    13 def auth(engine='file'):
    14     def xxx(func): # func=最原始那个index的内存地址
    15         def wrapper2(*args, **kwargs):
    16             print('================>wrapper2运行了')
    17             name=input('username>>>: ').strip()
    18             pwd=input('password>>>: ').strip()
    19             if engine == 'file':
    20                 print('基于文件的认证')
    21                 if name == 'egon' and pwd  == '123':
    22                     print('login successfull')
    23                     res = func(*args, **kwargs)
    24                     return res
    25             elif engine == 'mysql':
    26                 print('基于mysql的认证')
    27             elif engine == 'ldap':
    28                 print('基于ldap的认证')
    29             else:
    30                 print('错误的认证源')
    31         return wrapper2
    32     return xxx
    33 
    34 @timmer # index=timmer(wrapper2的内存地址) #index=wrapper1的内存地址
    35 @auth(engine='file') #@xxx #index=xxx(最原始那个index的内存地址) #index=wrapper2的内存地址
    36 def index():
    37     print('welcome to index page')
    38     time.sleep(2)
    39 
    40 index() #wrapper1的内存地址()
    # ==================================>wrapper1运行了
    # ===================================>wrapper2运行了
    # username>>>: egon
    # password>>>: 123
    # 基于文件的认证
    # login successfull
    # welcome to index page
    # run time is 11.126000165939331
     
     1 import time
     2 
     3 def timmer(func): #func=wrapper2的内存地址
     4     def wrapper1(*args, **kwargs):
     5         print('=================>wrapper1运行了')
     6         start=time.time()
     7         res = func(*args, **kwargs) #=================>跳到wrapper2去执行了,
     8         stop=time.time()
     9         print('run time is %s' %(stop - start))
    10         return res
    11     return wrapper1
    12 
    13 def auth(engine='file'):
    14     def xxx(func): # func=最原始那个index的内存地址
    15         def wrapper2(*args, **kwargs):
    16             print('===============>wrapper2运行了')
    17             name=input('username>>>: ').strip()
    18             pwd=input('password>>>: ').strip()
    19             if engine == 'file':
    20                 print('基于文件的认证')
    21                 if name == 'egon' and pwd  == '123':
    22                     print('login successfull')
    23                     res = func(*args, **kwargs)
    24                     return res
    25             elif engine == 'mysql':
    26                 print('基于mysql的认证')
    27             elif engine == 'ldap':
    28                 print('基于ldap的认证')
    29             else:
    30                 print('错误的认证源')
    31         return wrapper2
    32     return xxx
    33 
    34 @auth(engine='file')
    35 @timmer
    36 def index():
    37     print('welcome to index page')
    38     time.sleep(2)
    39 
    40 index() #wrapper1的内存地址()
    41
    #===================================>wrapper2运行了
    # username>>>: egon
    # password>>>: 123
    # 基于文件的认证
    # login successfull
    # ===================================>wrapper1运行了
    # welcome to index page
    # run time is 2.0189998149871826
    
    
  • 相关阅读:
    POJ3094 UVALive3594 HDU2734 ZOJ2812 Quicksum【进制】
    UVALive5583 UVA562 Dividing coins
    POJ1979 HDU1312 Red and Black【DFS】
    POJ1979 HDU1312 Red and Black【DFS】
    POJ2386 Lake Counting【DFS】
    POJ2386 Lake Counting【DFS】
    HDU4394 Digital Square
    HDU4394 Digital Square
    UVA213 UVALive5152 Message Decoding
    UVA213 UVALive5152 Message Decoding
  • 原文地址:https://www.cnblogs.com/xuechengeng/p/9711861.html
Copyright © 2020-2023  润新知