• python_装饰器


    # 装饰器形成的过程 : 最简单的装饰器 有返回值得  有一个参数  万能参数
    # 装饰器的作用
    # 原则 :开放封闭原则
    # 语法糖:@装饰函数名
    # 装饰器的固定模式

    import time
    # time.time()  # 获取当前时间
    # time.sleep() # 等待
    # 装饰带参数的装饰器
    def timer(f):   # 装饰函数
        def inner(*args,**kwargs):
            start = time.time()
            ret = f(*args,**kwargs)  # 被装饰函数
            end = time.time()
            print(end-start)
            return ret
        return inner
    @timer         # 语法糖 @装饰器函数名  在被装饰函数的上面
    def func(a):    #  被装饰的函数
        time.sleep(0.1)
        print('哈哈哈')
        return 'hello'
    
    
    # func = timer()
    
    ret = func()  # inner
    print(ret)



    # 装饰器的作用 不想修改函数的调用方式 但是还想再原来的函数前后添加功能
    # timmer 就是一个装饰函数,只是对一个函数 有一些装饰作用

    # 原则:开放封闭原则
    # 开放:对扩展是开放的
    # 封闭:对修改是封闭的

    # 装饰器的固定模式
    def wrapper(f):   # 装饰器函数,f是被装饰的函数
        def inner(*args,**kwargs):
            '''在被装饰函数之前要做的事'''
            ret = f(*args,**kwargs)    # 被装饰的函数
            '''在被装饰函数之后要做的事'''
            return ret
        return inner
    
    @wrapper     # func_name = wrapper(func_name)
    def func_name():
        print(123)
    
    ret = func_name
    装饰器的进阶
    # functools.wraps
    # 带参数的装饰器
    # 多个装饰器装饰同一个函数
    wraps
    
    def wahaha():
        '''打印这个函数'''
        pass
    print(wahaha.__name__)  # 查看字符串格式函数名
    print(wahaha.__doc__) # 查看函数注释
    
    from functools import wraps   # 引入wraps,全局被装饰的函数也能使用
    def wrapper(f):
        @wraps(f)   # 在这里装饰inner  作用保留原有函数的名称和docstring
        def inner(*args,**kwargs):
            '''在被装饰函数之前要做的事'''
            ret = f(*args,**kwargs)
            '''在被装饰函数之后要做的事'''
            return ret
        return inner
    
    @wrapper     # func_name = wrapper(func_name)
    def func_name():
        print(123)
    
    ret = func_name
    
    print(func_name.__name__)
    # 带参数的装饰器
    import time    # 引入时间模块
    flage = False   # 定义一个全局变量
    def timer_out(flage):   装饰器函数外面在裹一个函数
        def timer(func):
            def inner(*args,**kwargs):
                if flage:         # 加个判断
                    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 timer
    
    @timer_out(flage)   #这里要明白 timer_out(flage) = timer ,所以还是@timer  
    def wahaha():
        time.sleep(0.1)
        print('hehei')
    
    @timer_out(flage)
    def hel():
        time.sleep(0.1)
        print('lalala')
    
    wahaha()
    hel()
    # 多个装饰器装饰一个函数
    def wrapper1(func):
        def inner1():
            print('wrapperl,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
    
    @wrapper1
    @wrapper2       #距离最近的先执行,这个要好好理解执行变化
    def f():
        print('in f')
    f()
    # 1.编写装饰器,为多个函数加上认证的功能(用户的账户密码来源于文件)要求登录成功一次,后续的函数都无需再输入用户名和密码
    flat = False   #定义一个全局变量 好像其他也能代替
    def login(func):
        def inner(*args,**kwargs):
            global flat     # 这里不能用nonlocal声明
            '''先登录程序'''
            if flat:
                ret = func(*args,**kwargs)
                return ret
            else:
                username = input('username:')
                password = input('password:')
                if username == 'boss' and password == '666666':
                    flat = True
                    ret = func(*args,**kwargs)
                    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('删除一件物品')
    # 进阶作业(选做)
    # 1.编写下载网页内容的函数,要求功能是:用户传入一个URL,函数返回下载页面的结果
    from urllib.request import urlopen
    def get(url):
        code = urlopen(url).read
        return code
    ret =get('http://www.baidu.com')
    print(ret)
    #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)
            with open('web_cache','wb') as f:
                f.write(ret)
            return ret
        return inner
    
    @cache
    def get(url):
        code = urlopen(url).read()
        return code
    
    ret = get('http://www.baidu.com')
    print(ret)
  • 相关阅读:
    NOI2005瑰丽华尔兹
    BZOJ4919[Lydsy1706月赛]大根堆
    BZOJ1097[POI2007]ATR-Tourist Attractions
    Luogu2973 [USACO10HOL]Driving Out the Piggies G
    Luogu5505 JSOI2011分特产
    Luogu1450 HAOI2008硬币购物
    NOI2001 炮兵阵地
    汕头市队赛 SRM 09 A 撕书
    洛谷P1196 银河英雄传说
    洛谷P3144 [USACO16OPEN]关闭农场Closing the Farm
  • 原文地址:https://www.cnblogs.com/niunai/p/10553947.html
Copyright © 2020-2023  润新知