• 29 Mar 18 函数 有参、无参装饰器


    一、无参装饰器及其升级版
    1 开放封闭原则
    软件一旦上线后,就应该遵循开放封闭原则,即对修改源代码是封闭的,对功能的扩展是开放的。也就是说我们必须找到一种解决方案:能够在不修改一个功能源代码以及调用方式的前提下,为其加上新功能。
     
    总结原则如下:
    1、不修改源代码
    2、不修改调用方式
    目的:在遵循1和2原则的基础上扩展新功能
     
    2、什么是装饰器?
    器指的工具,装饰指的是为被装饰对象添加新功能。装饰器即在不修改被装饰对象源代码与调用方式的前提下,为被装饰器对象添加新功能。
     
    装饰器与被装饰的对象均可以是任意可调用的对象
    装饰器=》函数
    被装饰的对象=》函数
     
    3、给函数加上了功能,但改变了原代码
    import time
     
    def index():
        start_time=time.time()   #time.time()调的是1970年至现在一共过了多少秒
        time.sleep(3)
        print('welcome to index page')
        stop_time=time.time()
        print('run time is %s' %(stop_time-start_time))
     
    index()
     
    4. 没有把常用功能抽象成函数,需要反复输入
    import time
     
    def index():
        time.sleep(3)
        print('welcome to index page')
     
    def home(name):
        time.sleep(5)
        print('welcome %s to home page' %name)
     
    start_time=time.time()
    index()
    stop_time = time.time()
    print('run time is %s' % (stop_time - start_time))
     
    start_time=time.time()
    home('egon')
    stop_time = time.time()
    print('run time is %s' % (stop_time - start_time))
     
    5、修改了原函数的调用方式,即无法用index()的形式直接调用
    import time
     
    def index():
        time.sleep(3)
        print('welcome to index page')
     
    def home(name):
        time.sleep(5)
        print('welcome %s to home page' %name)
     
    def wrapper(func): #func=index
        start_time=time.time()
        func() #index()
        stop_time = time.time()
        print('run time is %s' % (stop_time - start_time))
     
    wrapper(index) # 修改了原函数的调用方式
     
    6、 初步解决了问题,但没有考虑到原参数带返回值,或带参数的情况
    import time
     
    def index():
        time.sleep(3)
        print('welcome to index page')
     
    def outter(func): #func=最原始的index
        # func=最原始的index
        def wrapper():
            start_time=time.time()
            func()
            stop_time=time.time()
            print(stop_time-start_time)
        return wrapper
     
    index=outter(index) # 新的index=wrapper
    index() #wrapper()
     
    7、 考虑了原参数带返回值或参数的问题,但每次都要加上index=timmer(index)
    import time
     
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
     
    def home(name):
        time.sleep(2)
        print('welcome %s to home page' %name)
     
    #==============装饰器
    def timmer(func):
        #func=最原始的home
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs) #调用最原始的home
            stop_time=time.time()
            print(stop_time-start_time)
            return res
        return wrapper
     
    index=timmer(index) # 新的index=wrapper
    home=timmer(home) #新的home=wrapper
    # ==========================================
    index()
    home('egon')
     
    无参装饰器模板
    def outer(func):
        def inner(*args,**kwargs):
            res=func(*args,**kwargs)
            return res
        return inner
     
    8、运用装饰器语法糖 @timmer #index=timmer(index)
    @timmer必须放在原函数的正上方, 
    timmer的函数体要放在@timmer之前
    如果要用装饰器加@。。。,如果不用注释掉@
     
    import time
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print(stop_time-start_time)
            return res
        return wrapper
     
    @timmer #index=timmer(index)
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
     
    @timmer # home=timmer(home)
    def home(name):
        time.sleep(2)
        print('welcome %s to home page' %name)
     
    index()
    home('egon')
     
    9、认证装饰器实现(另一个例子)
    import time
    current_user={
        'username':None,
        # 'login_time':None
    }
     
    def auth(func):
        # func=index
        def wrapper(*args,**kwargs):
            if current_user['username']:
                print('已经登陆过了')
                res=func(*args,**kwargs)
                return res
     
            uname=input('用户名>>: ').strip()
            pwd=input('密码>>: ').strip()
            if uname == 'egon' and pwd == '123':
                print('登陆成功')
                current_user['username']=uname
                res=func(*args,**kwargs)
                return res
            else:
                print('用户名或密码错误')
        return wrapper
     
    @auth #index=auth(index)
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
     
    @auth
    def home(name):
        time.sleep(2)
        print('welcome %s to home page' %name)
     
    index()
    home('egon')
     
    10、叠加多个装饰器,上面的装饰器作用为:下方装饰器+原函数
    import time
    current_user={
        'username':None,
        # 'login_time':None
    }
     
    def auth(func):
        # func=index
        def wrapper(*args,**kwargs):
            if current_user['username']:
                print('已经登陆过了')
                res=func(*args,**kwargs)
                return res
     
            uname=input('用户名>>: ').strip()
            pwd=input('密码>>: ').strip()
            if uname == 'egon' and pwd == '123':
                print('登陆成功')
                current_user['username']=uname
                res=func(*args,**kwargs)
                return res
            else:
                print('用户名或密码错误')
        return wrapper
     
    def timmer(func):
        def wrapper(*args,**kwargs):
            start_time=time.time()
            res=func(*args,**kwargs)
            stop_time=time.time()
            print(stop_time-start_time)
            return res
        return wrapper
     
    @timmer # timmer 统计的是auth+index的执行时间
    @auth
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
     
    index()
     
    二、有参数的装饰器 #再包上一层,函数的参数可以为一个,也可为多个
    import time
    current_user={
        'username':None,
        # 'login_time':None
    }
     
    def auth(engine):
        # engine='file'
        def auth2(func):
            # func=index
            def wrapper(*args,**kwargs):
                if engine == 'file':
                    if current_user['username']:
                        print('已经登陆过了')
                        res=func(*args,**kwargs)
                        return res
     
                    uname=input('用户名>>: ').strip()
                    pwd=input('密码>>: ').strip()
                    if uname == 'egon' and pwd == '123':
                        print('登陆成功')
                        current_user['username']=uname
                        res=func(*args,**kwargs)
                        return res
                    else:
                        print('用户名或密码错误')
                elif engine == 'mysql':
                    print('基于MyQL的认证')
                elif engine == 'ldap':
                    print('基于LDAP的认证')
            return wrapper
        return auth2
     
    @auth('ldap') #@auth2 #index=auth2(index) #index=wrapper
    def index():
        time.sleep(1)
        print('welcome to index page')
        return 122
     
    index() # wrapper()
  • 相关阅读:
    服务器RAID5阵列掉了两块盘恢复数据过程
    sql server数据库错误数据恢复过程
    raid崩溃导致存储虚拟化平台数据丢失
    详解MBR分区结构以及GPT分区结构
    存储硬件故障如何恢复数据库
    服务器raid常见故障解决方案
    误删除VMware虚拟机vmdk文件的恢复方法
    HP P2000 服务器数据恢复+服务器数据恢复通用办法
    DELL EqualLogic PS6100存储数据丢失的解决方案
    IBM DS4800服务器RAID信息丢失数据恢复方法
  • 原文地址:https://www.cnblogs.com/zhangyaqian/p/py20180329.html
Copyright © 2020-2023  润新知