• 函数装饰器


    装饰器
      什么是装饰器
      器,指的就一种种工具,列如生活中的,刮毛器
      装饰,指的是给某个已存在的对象添加装饰品
      装饰器的目的是为了给这个被装饰对象,提价新功能或者说,增加某种能力
      在程序中工具就是函数
      如此一来,装饰器指也就是一个函数,被装饰者也是一个函数
      总结:装饰器就是用一个函数去扩展另一个已存在的函数的功能
      扩展是对于一个应用程序来水非常重要的能力,任何应用程序都需要扩展,于是出现了开闭原则
      开闭原则
        对修改关闭,对扩展开放
        不允许修改源代码以及调方式
      装饰器就是一种可以保证不修改源代码,也不修改调用方式,还能给函数增加新功能的方式
    需求:目前已有一个函数,其功能是从服务器下载一个文件,需求要为这个函数统计下载耗时
    # import time
    # 现有的已经投入使用的下载功能
    # def download(filepath):
    # print('开始下载%s....'%filepath)
    # time.sleep(3)
    # print('%s下载完成'%filepath)
    # return '123'
    # 现有的已经投入使用的上传功能
    # def upload():
    # print('开始上传。。。')
    # time.sleep(3)
    # print('上传完成。。。')
    # download('毒液')
    #测试1
    # def download():
    # boot_time=time.time()
    # print('开始下载毒液。。。')
    # time.sleep(3)
    # print('毒液下载完成。。。')
    # print('耗时:',time.time()-boot_time)
    # download()
    # 测试2
    # boot_time=time.time()
    # download()
    # print('耗时:',time.time()-boot_time)
    # 测试3
    # def outer(func):
    # def run_time(*args,**kwargs):
    # boot_time=time.time()
    # res=func(*args,**kwargs)
    # print('耗时:', time.time() - boot_time)
    # 修改了调用方式
    # run_time(download)
    # run_time(upload)
    # 测试4
    # def outer(func):
    # def run_time(*args,**kwargs):
    # boot_time=time.time()
    # res=func(*args,**kwargs)
    # print('耗时:', time.time() - boot_time)
    # return res#把原始函数的执行结果 再交给调用者
    # return run_time
    # print(download)
    # # 修改了调用方式
    # download=outer(download)#res is run_time
    # movie=download('大电影。。。')
    # print(movie)
    #
    # upload=outer(upload)
    # upload()
    # print(download)
    # 统计时间
    # boot_time=time.time()
    # print(boot_time)
    # for i in range(10):
    # print('hello')
    # print(time.time()-boot_time)
    装饰器的模板
    # def download():
    # pass
    # def outer(func):
    # def wrapper():
    # print('扩展的新功能')
    # func()
    # print('扩展的新功能')
    # return wrapper
    # import time
    # # 原始函数
    # def test():
    # print('test run ')
    # 记录执行时间的装饰器
    # def outer(func):
    # def wrapper():
    # '''
    # 新功能
    # :return:
    # '''
    # print('时间:',time.time(),'run:',func)
    # func()
    # return wrapper
    # test=outer(test)
    # test()
    装饰器的语法糖
      语法糖
    就是一种简便写法,使你的语法更简洁
    提供输出日记(日志 什么时候干了什么事)功能
    # import time
    # # 原始函数
    # def test():
    # print('test run ')
    # 记录执行时间的装饰器
    # def outer(func):
    # def wrapper():
    # '''
    # 新功能
    # :return:
    # '''
    # print('时间:',time.time(),'run:',func)
    # func()
    # return wrapper
    # test=outer(test)
    # test()
    import time
    def logger(func):
    def wrapper(*args,**kwargs):
    print('时间:%s func:%s' %(time.time(),func.__name__))
    res=func(*args,**kwargs)
    return res
    return wrapper
    #该语法就可以帮我们完成对原始函数的伪装
    # 注意1.必须写在被装饰函数的正上方
    # 注意2.在开发时装饰器必须写在被装饰器函数之上
    @logger #login =login(login)
    def login():
    print('登陆成功...')
    login()
    1.无参装饰器
    import time
    def download():
    print('download run')
    def outer(func):
    def run_time(*args,**kwargs):#是为了让装饰器函数能接受任何形式任何长度的参数
    boot_time=time.time()
    res=func(*args,**kwargs)#将参数子啊原模原样交给被装饰者
    print('耗时:',time.time()-boot_time)
    return res#把原函数的执行结果 再交给调用者
    return run_time
    download=outer(download)
    # 使用者
    download()
    同时叠加多个装饰器
    import time
    # 装饰器1
    def logger(func):
    def wrapper(*args,**kwargs):
    print('时间:%s func:%s' %(time.time(),func.__name__))
    res=func(*args,**kwargs)
    return res
    return wrapper
    # 装饰器2
    def timer(func):
    def run_time(*args,**kwargs):
    boot_time=time.time()
    res=func(*args,**kwargs)#这是子啊执行原始的download函数也就是被装饰的函数
    print('耗时:',time.time()-boot_time)
    return res#把原始的函数的执行结果 再交给调用者
    return run_time
    # 该语法就可以帮我们完成对原始函数的伪装
    # 注意1.必须写在被装饰函数的正上方
    # 注意2.在开发时装饰器必须写在被装饰器函数之上
    @time #logger=timer(logger)
    @logger #login=logger(login)
    def login():
    print('登陆成功')
    login()
    # 在嵌套多个装饰器时,执行的顺序是从上往下依次调用,结束的顺序反过来,是从下往上
    # 实际开发中 没什么用。。。
    装饰器在购物车中的应用
    is_login = False


    # 判断是否登陆过的装饰器
    def auth(func):
    def wrapper(*args, **kwargs):
    if is_login:
    func(*args, **kwargs)
    else:
    print('还没有登陆过请先登陆。。')

    return wrapper


    def login():
    global is_login
    name = input('请输入用户名').strip()
    pwd = input('请输入密码').strip()
    if name == 'sss' and pwd == '123':
    print('登录成功')
    is_login = True


    @auth
    def shopping():
    print('查看购物车。。。')


    @auth
    def collection():
    print('查看收藏。。。')


    def main():
    while True:
    funcs = {'1': login, '2': shopping, '3': collection}
    print('''
    1.登陆
    2.查看购物车
    3.查看收藏
    ''')
    res = input('请输入编号').strip()
    if res in funcs:
    funcs[res]()
    else:
    print('输入有误')


    main()
    2.有参装饰器

    需求: 提供一个用于输出日志的装饰器,可以指定日志的输出位置是打印到控制台或是文件中
    import time


    def outer(location):
    def logger(func):
    def wrapper(*args, **kwargs):
    if location == 'cmd':
    print("时间:%s func:%s" % (time.time(), func.__name__))
    elif location == 'file':
    with open('a.log', 'a', encoding='utf-8') as f:
    f.write("时间:%s func:%s" % (time.time(), func.__name__))
    else:
    print('位置错误。。。。')
    return func(*args, **kwargs)

    return wrapper

    return logger


    # @logger
    def test():
    print('test run')
    res = outer('file')
    test = res(test)
    test()

     

    from functools import wraps
    import time


    def outer(location):
    def logger(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
    '''
    这是装饰器函数
    :param args:
    :param kwargs:
    :return:
    '''
    if location == 'cmd':
    print("时间:%s func:%s" % (time.time(), func.__name__))
    elif location == 'file':
    with open('a.log', 'a', encoding='utf-8') as f:
    f.write("时间:%s func:%s" % (time.time(), func.__name__))
    else:
    print('位置错误。。。。。。')
    return func(*args, **kwargs)

    return wrapper

    return logger


    @outer('file') # logger=outer('file') test=logger(test)
    def test():
    '''
    这是一个test函数
    :return:
    '''
    print('test run')


    # test()
    print(test.__doc__)


    def f1():
    '''
    这是个f1函数
    :return:
    '''


    # __doc__可以获取文档注释内容
    print(f1.__doc__)

  • 相关阅读:
    如何参与linux 内核开发
    绘制dot 图
    GITHUB 提交错误 Error: Permission denied (publickey) 解决
    atomic_read
    linux 获取cpu 个数
    【转】 管理CPU 亲和性
    【转】 申请对齐某种结构体大小的buffer
    WePY框架开发的小程序中使用 echarts折线图
    vue + css3 实现主题色切换
    vue 中 const { x } = this 的用法
  • 原文地址:https://www.cnblogs.com/ShenJunHui6/p/10272694.html
Copyright © 2020-2023  润新知