1.4 装饰器实战实例

装饰器的详细介绍可参考:https:#www.runoob.com/w3cnote/python-func-decorators.html

1 装饰器的属性:

实质:函数,应用在 类、方法、函数 上 参数:要装饰的函数名(非函数调用) 返回:装饰完的函数名(非函数调用) 作用:在原有函数实现功能的基础上不改变其任何操作,实现额外的功能扩展 特点:基于现有的对象不需要做代码上的变动 应用场景:插入日志、性能测试、事务处理、权限校验等

2 装饰器参数:

1)如被装饰的方法或函数存在参数,则需要通过装饰器的内层函数将参数传递 2)被装饰的函数调用时是否存在返回值,取决于内层函数是否将值进行返回 3)如装饰器需要传参,则需要三层函数,此时第二层函数固定传入被装饰函数的对象,第一层函数传入的参数即为装饰器所传入的参数

3 系统装饰器

1)类装饰器 @classmethod

通过类名直接调用其属性和方法(还有种是,通过创建对象调用),但属性必须是类属性,不能调用对象属性; 方法必须通过 @classmethod 进行装饰,不能调用对象方法; 装饰方法的第一个参数默认是 cls(表示传入当前的类) 类只能调用类属性和类方法,不能调用对象属性和对象方法; 但对象实例 既可以调用类属性、类方法,也可调用 对象属性、对象方法

2)静态方法装饰器 @staticmethod

该方法不需要传递任何参数,既可以通过类调用,也可通过对象调用 只能够调用类属性和类方法,不能调用实例方法 所有对象及类 共享同一份静态属性和方法

4 时间装饰器

需求:在不改变其代码的情况下,完成检测任意一段代码的执行时间 分析:先定义一个timer装饰器,然后将该装饰器装饰在需要检测代码运行时间的程序块上

# 时间装饰器

import time


# 装饰器timer,其中function为要装饰的函数
def timer(function):
    def wrapper():
        time_start = time.time()
        function()
        time_end = time.time()
        spend_time = time_end - time_start
        print(f"花费的时间是{spend_time}秒")

    return wrapper


def timer1(function):  # 第一层:传入的参数即为装饰器所传入的参数
    def wrapper(*args, **kw): # 第二层:固定传入被装饰函数的对象
        time_start = time.time()
        function(*args, **kw) # 第三层:被装饰的函数的参数
        time_end = time.time()
        spend_time = time_end - time_start
        print(f"花费的时间是{spend_time}秒")

    return wrapper


@timer
def get_sum():
    sum = 0
    for i in range(1, 100001):
        sum += i
    print(f"累计和{sum}")
   

@timer1
def get_sum1():
    sum = 0
    for i in range(1, 100001):
        sum += i
    print(f"累计和1{sum}")


if __name__ == '__main__':
    get_sum()
    get_sum1()
def cal_ten_outer(number):      # 第一层:传入的参数即为装饰器所传入的参数
    def cal_ten_test(func):     # 第二层:固定传入被装饰函数的对象
        def cal_ten(a, b):      # 第三层:被装饰的函数的参数
            if number > 10:
                return func(a, b) - 10
            else:
                return func(a, b) + 10
        return cal_ten
    return cal_ten_test

@cal_ten_outer(11)
def add(a, b):
    return a + b

if __name__ == '__main__':
    print(add(1, 6))

5 自定义装饰器

@Decorator装饰在func函数上实际等价于调用p = Decorator(func) p() 解释:代码执行过程中,首先p是类Decorator的一个实例,实现了_call_()方法后,p可以直接被调用,然后传入的参数func就是被装饰在func函数的函数对象,所以会先输出decorator start然后调用func函数执行,最后输出decorator 注意:call()是一个特殊方法,他可以将一个实例变成一个可调用对象,要使用类装饰器,必须实现类中的_call_()方法,就相当于将实例变成了一个方法

class Decorator(object):
    def __init__(self, func_name):
        self.func_name = func_name

    def __call__(self):
        print("decorator start")
        self.func_name()
        print("decorator end")


@Decorator
def func():
    print("func")


if __name__ == '__main__':
    func()