zoukankan      html  css  js  c++  java
  • 装饰器

    一、装饰器

    装饰:装修,房子就是可以住的,如果装修,不影响你住,而且体验更加,让你生活中增加了很多功能:洗澡,看电视,沙发休息。

    器:工具

    开放封闭原则:

    开放:对代码的拓展是开放的。

    封闭:对源码的修改是封闭的。

     

    装饰器:完全遵循开放封闭原则,装饰器就是一个函数。

    在不改变原函数代码以及调用方式前提下,为其增加新的功能。本质是闭包

    标准版。

    def wrapper(f):                     # f 为被装饰函数
        def inner(*args, **kwargs):     # 给被装饰函数传参
            '''添加额外的功能:被执行装饰函数之前的操作'''
            ret = f(*args, **kwargs)
            '''添加额外的功能:被执行装饰函数之后的操作'''
            return ret                  # 返回被装饰函数的返回值
        return inner

    举例:给index函数新增一个功能测试函数执行效率:

    import time
    ​
    def timmer(f):                      # 装饰器要写在最前面。f 是被装饰函数。
            # 当装饰dariy函数时,函数的定义:* 聚合  args = ('小杨',20)
        def inner(*args, **kwargs):     # 因为实际执行的是inner,用inner传参给被装饰函数
            start_time = time.time()
            # 函数的执行:* 打散:f(*args) --> f(*('小杨',20))  --> f('小杨',20)
            r = f(*args, **kwargs)      # 给被装饰函数传参,在此处被传进去的参数会被打散,并且被装饰函数的返回值赋给r,
            end_time = time.time()
            print(f'测试函数的执行效率:{end_time - start_time}')
            return r                    # 返回被装饰函数的返回值
        return inner
    ​
    @timmer         # 相当于  index = timmer(index)
    def index(name):
        '''
        有很多代码.....
        '''
        time.sleep(0.5)  # 模拟网络延迟或者代码效率。
        print(f'欢迎{name}登录博客首页')
        return 'index的返回值:666'
    ​
    @timmer
    def dariy(name,age):
        '''
        有很多代码.....
        '''
        time.sleep(0.5)  # 模拟网络延迟或者代码效率。
        print(f'欢迎{age}岁的{name}登录日记首页')
    ​
    ret = index('小杨')       # 相当于--》ret = inner('小杨')
    print(ret)               # 打印index的返回值,实际上是inner的返回值,在inner函数那里做了个转换
    print('---------------')
    dariy('小杨', 20)         # 相当于--》inner('小杨', 20)

    二、带参数的装饰器

    标准版

    def parameter(path):                    # 给wrapper装饰器传入参数
        def wrapper(f):                     # f 为被装饰函数
            def inner(*args, **kwargs):     # 给被装饰函数传参
                '''添加额外的功能:被执行装饰函数之前的操作'''
                f'''给装饰器传入的参数是:{path}'''
                ret = f(*args, **kwargs)
                '''添加额外的功能:被执行装饰函数之后的操作'''
                return ret                  # 返回被装饰函数的返回值
            return inner
        return wrapper

    在函数到@wrapper时会变成——>被装饰函数 = inner(被装饰函数)

    在当遇到带参数的装饰器时@parameter('abc')会变成——>先执行parameter('abc')函数,并返回值wrapper之后就是正常装饰器了@wrapper。

    列如:将每个模块的调用日志写进相应的日志文件里面去

    import time
    ​
    ​
    def parameter(path):            # 将日志文件名传入装饰器里
        def wrapper(f):
            def inner(*args, **kwargs):
                with open(path, encoding='utf-8', mode='a') as f1:  
                    f1.write(f'访问时间{time.strftime("%Y-%m-%d %H:%M:%S")},函数名{f.__name__}')
                ret = f(*args, **kwargs)
                return ret
            return inner
        return wrapper
    ​
    @parameter('login.txt') # 相当于-->wrapper = parameter('login.txt')
    def login():
        print('欢迎登录:')
    ​
    @parameter('register.txt')
    def register():
        print('欢迎注册:')
    ​
    @parameter('goods.txt')
    def goods():
        print('欢迎购物:')
    ​
    ​
    goods()
    login()
    register()
    学习之旅
  • 相关阅读:
    python的深拷贝和浅拷贝
    jquery的each循环
    python开发要求
    Python的进程和线程(二)——IO密集型任务
    Python的进程和线程(一)——计算密集型任务
    Python常用模块(一)--argparse模块
    Chrome Headless模式(二)——Python+selenium+headerless
    beyond compare 命令行批量比对图片
    Chrome Headless模式(一)
    python实现在mac笔记本上更换桌面背景
  • 原文地址:https://www.cnblogs.com/XiaoYang-sir/p/14675637.html
Copyright © 2011-2022 走看看