装饰器

一、装饰器

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

器:工具

开放封闭原则:

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

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

 

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

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

标准版。

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()
学习之旅
原文地址:https://www.cnblogs.com/XiaoYang-sir/p/14675637.html