zoukankan      html  css  js  c++  java
  • 19 装饰器进阶

    # 装饰器的进阶
    # functools.wraps
    # 带参数的装饰器
    # 多个装饰器装饰同一个函数
    # 周末的作业
    # 文件操作
    # 字符串处理
    # 输入输出
    # 流程控制

    # 装饰器
    # 开发原则 : 开放封闭原则
    # 装饰器的作用 :在不改变原函数的调用方式的情况下,在函数的前后添加功能
    # 装饰器的本质 : 闭包函数

    def wrapper(func):
        def inner(*args,**kwargs):
            print('在此添加调用前代码')
            ret = func(*args,*kwargs)
            print('在此添加调用后代码')
            return ret
        return inner
    
    @wrapper
    def holiday(day):
        print('全体放假 %s 天' % day)
        return '好开心'
    
    ret = holiday(3)
    print(ret)
    '''
    在此添加调用前代码
    全体放假 3 天
    在此添加调用后代码
    好开心
    '''
    def outer(*args,**kwargs):
        print(args)                     #(1, 2, 3, 4)
        print(*args)                    #1 2 3 4
        def inner(*args):
            print('inner:',args)       #inner: (1, 2, 3, 4)
        inner(*args)
    
    outer(1,2,3,4)
    #
    outer(*[1,2,3,4])
    #
    outer(*(1,2,3,4))
    def wahaha():
        '''
        一个打印娃哈哈的函数
        :return:
        '''
        print('娃哈哈')
    
    print(wahaha.__name__)  #查看函数名     wahaha
    print(wahaha.__doc__)   #查看注释文档
    #带参数的装饰器
    from functools import wraps     #调用一个装饰函数
    def wrapper(func):
        @wraps(func)                 #装饰函数
        def inner(*args,**kwargs):
            print('在此添加调用前代码')
            ret = func(*args,*kwargs)
            print('在此添加调用后代码')
            return ret
        return inner
    
    @wrapper
    def holiday(day):
        '''
        这是一个放假通知
        :param day:
        :return:
        '''
        print('全体放假 %s 天' % day)
        return '好开心'
    
    ret = holiday(3)
    print(ret)
    print(holiday.__name__)         #holiday
    print(holiday.__doc__)
    #    这是一个放假通知
    #    :param
    #    day:
    #    :return:

     # 1、编写装饰器,为多个函数加上认证的功能(用户的账号密码来源于文件),

    # 要求登录成功一次,后续的函数都无需再输入用户名和密码
    FLAG = False
    def login(func):
        def inner(*args,**kwargs):
            global FLAG
            '''登录程序'''
            if FLAG:
                ret = func(*args, **kwargs)  # func是被装饰的函数
                return ret
            else:
                username = input('username : ')
                password = input('password : ')
                if username == 'boss_gold' and password == '22222':
                    FLAG = True
                    ret = func(*args,**kwargs)      #func是被装饰的函数
                    return ret
                else:
                    print('登录失败')
        return inner
    
    @login
    def shoplist_add():
        print('增加一件物品')
    
    @login
    def shoplist_del():
        print('删除一件物品')
    
    shoplist_add()
    shoplist_del()
    # 2、编写装饰器,为多个函数加上记录调用功能,要求每次调用函数都将被调用的函数名称
    # 写入文件
    def log(func):
        def inner(*args,**kwargs):
            with open('log','a',encoding='utf-8') as f:
                f.write(func.__name__+'
    ')
            ret = func(*args,**kwargs)
            return ret
        return inner
    
    @log
    def shoplist_add():
        print('增加一件物品')
    
    @log
    def shoplist_del():
        print('删除一件物品')
    
    shoplist_add()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    shoplist_del()
    # 进阶作业:
    # 1、编写下载网页内容的函数,要求功能是:用户传入一个url,函数返回下载页面的结果
    # 2、为题目1编写装饰器,实现缓存网页内容的功能
    # 具体:实现下载的页面存放于文件中,如果文件内有值(文件大小不为0),就优先从文件
    # 中读取网页内容,否则,就去下载,然后存到文件中
    import os
    from urllib.request import urlopen
    def cache(func):
        def inner(*args,**kwargs):
            if os.path.getsize('web_cache'):
                with open('web_cache','rb') as f:
                    return f.read()
            ret = func(*args,**kwargs)  #get()
            with open('web_cache','wb') as f:
                f.write(b'*********'+ret)
            return ret
        return inner
    
    @cache
    def get(url):
        code = urlopen(url).read()
        return code
    
    
    # {'网址':"文件名"}
    ret = get('http://www.baidu.com')
    print(ret)
    ret = get('http://www.baidu.com')
    print(ret)
    ret = get('http://www.baidu.com')
    print(ret)
    #带参数的装饰器
    #500个函数
    import time
    FLAGE = False
    def timmer_out(flag):
        def timmer(func):
            def inner(*args,**kwargs):
                if flag:
                    start = time.time()
                    ret = func(*args,**kwargs)
                    end = time.time()
                    print(end-start)
                    return ret
                else:
                    ret = func(*args, **kwargs)
                    return ret
            return inner
        return timmer
    # timmer = timmer_out(FLAGE)
    @timmer_out(FLAGE)    #wahaha = timmer(wahaha)
    def wahaha():
        time.sleep(0.1)
        print('wahahahahahaha')
    
    @timmer_out(FLAGE)
    def erguotou():
        time.sleep(0.1)
        print('erguotoutoutou')
    
    wahaha()
    erguotou()
    #多个装饰器装饰一个函数
    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())
     
  • 相关阅读:
    dp,路径保存,最大公共上升子序列——ZOJ
    简单dp——HDU
    扫描线,线段树,离散化——HDU
    c++版本的opencv3.4.1里分类器输出值异常
    win10家庭版openssh连接远程服务器显示connetion reset
    生活感悟一
    Teradata简介
    kettle 无法正常启动问题
    kettle实现同构单表增量同步
    kettle数据库连接使用变量
  • 原文地址:https://www.cnblogs.com/bydzxzy/p/9651550.html
Copyright © 2011-2022 走看看