python进阶二:函数装饰器、类装饰器、如何保证原函数的元信息、装饰器嵌套、装饰器应用场景

    技术2024-01-16  96

    装饰器

    一、简单装饰器

    def my_decorator(func): def wrapper(): print('wrapper of decorator!') func() return wrapper def greet(): print('halo world!') greet = my_decorator(greet) greet() # 输出 wrapper of decorator! hello world! @my_decorator def greet2(): print('halo world2!') greet2() # 输出 wrapper of decorator! hello world2!

    这里my_decorator()为装饰器,将greet()包含在其中,改变了greet函数的行为,但是原函数greet并没变。不改变原函数的情况下,改变函数的行为。

    调用方法:

    1、像greet函数中进行调用

    greet = my_decorator(greet) greet()

    2、像greet2函数中进行调用 @my_decorator

    这里的@称之为语法糖

    二、带有参数的装饰器

    def my_decorator(func): def wrapper(*args, **kwargs): print('wrapper of decorator!') func(*args, **kwargs) return wrapper @my_decorator def greet(message): print(message) greet('halo world!') # 输出 wrapper of decorator! halo world!

    三、带有自定义参数的装饰器

    举例:如果想让一个函数执行多次,可以写成

    def repeat(num): def my_decorator(func): def wrapper(*args, **kwargs): for i in range(num): print('wrapper of decorator') func(*args, **kwargs) return wrapper return my_decorator @repeat(4) def greet(message): print(message) greet('hello world') # 输出: wrapper of decorator hello world wrapper of decorator hello world wrapper of decorator hello world wrapper of decorator hello world

    四、原函数的元信息

    greet.__name__ ## 输出 wrapper

    以上可知,原函数元信息改变,greet函数被wrapper函数取代

    解决:采用内置装饰器@functools.wraps(func),将原函数的元信息拷贝到对应装饰器函数

    import functools def my_decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('wrapper of decorator!') func(*args, **kwargs) return wrapper @my_decorator def greet(message): print(message) greet.__name__ # 输出 'greet'

    五、类装饰器

    主要依赖于函数_call_()

    import time class TimeCount: def __init__(self, func): self.func = func def __call__(self, *args, **kwargs): start_time = time.time() self.func() end_time = time.time() print(f'执行函数时间为:{start_time-end_time}') @TimeCount def greet(): time.sleep(2) greet()

    六、装饰器嵌套

    @decorator1 @decorator2 @decorator3 def func(): ...

    执行顺序:从里向外

    decorator1(decorator2(decorator3(func))) import functools def my_decorator1(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('execute decorator1') func(*args, **kwargs) return wrapper def my_decorator2(func): @functools.wraps(func) def wrapper(*args, **kwargs): print('execute decorator2') func(*args, **kwargs) return wrapper @my_decorator1 @my_decorator2 def greet(message): print(message) greet('hello world') # 输出 execute decorator1 execute decorator2 hello world

    七、应用场景

    身份认证、日志、缓存、输入合法性检查等

    Processed: 0.011, SQL: 9