zoukankan      html  css  js  c++  java
  • 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)
  • 相关阅读:
    PAT (Advanced Level) 1010. Radix (25)
    PAT (Advanced Level) 1009. Product of Polynomials (25)
    PAT (Advanced Level) 1008. Elevator (20)
    PAT (Advanced Level) 1007. Maximum Subsequence Sum (25)
    PAT (Advanced Level) 1006. Sign In and Sign Out (25)
    PAT (Advanced Level) 1005. Spell It Right (20)
    PAT (Advanced Level) 1004. Counting Leaves (30)
    PAT (Advanced Level) 1001. A+B Format (20)
    PAT (Advanced Level) 1002. A+B for Polynomials (25)
    PAT (Advanced Level) 1003. Emergency (25)
  • 原文地址:https://www.cnblogs.com/niunai/p/10553947.html
Copyright © 2011-2022 走看看