【Python】学点装饰器(2)



接上一篇:
1、【Python】学点装饰器(1)



1. 不带参数的类装饰器

基于类的装饰器的实现,必须实现__call____init__两个内置函数:

  • __call__:接收被装饰的函数;
  • __init__:实现装饰逻辑

1.1 类装饰器实现

日志打印装饰器

class logger(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("[INFO]: the function {func}() is running...".format(func=self.func.__name__))
        return self.func(*args, **kwargs)

1.2 类装饰器应用

@logger
def say_some(something):
    print("I say {}!".format(something))

if __name__ == "__main__":
    say_some("你好")

运行结果:

[INFO]: the function say_some() is running...
I say 你好!

2. 带参数的类装饰器

  • 不带参数的装饰器,只能打印出INFO级别的日志,那如果需要打印WARNINGDEBUG等级别的日志的话,就需要给类装饰器传入参数,给这个函数指定级别;
  • 带参数和不带参数的装饰器有很大区别:
    • __init__:不再接收被装饰函数,而是接收传入参数;
    • __call__:接收被装饰函数,实现装饰逻辑;

2.1 带参数的类装饰器例子实现

class LoggerDecorator(object):
    def __init__(self, level='INFO'):
        self.level = level

    def __call__(self, func):
        def wrapper(*args, **kwargs):
            print("[{level}]: the function {func}() is running...".format(level=self.level,func=func.__name__))
            func(*args, **kwargs)
        return wrapper
@LoggerDecorator(level='DEBUG')
def say_some(some):
    print("say {}!".format(some))

if __name__ == "__main__":
    say_some("hello")

运行结果:

  • 这里执定level级别为DEBUG
[DEBUG]: the function say_some() is running...
say hello!

3. 使用偏函数和类实现装饰器

Python 对某个对象是否能通过装饰器( @decorator)形式使用只有一个要求:decorator 必须是一个“可被调用(callable)的对象。对于这个callable对象,我们最熟悉的就是函数了,绝大多数装饰器都是基于函数和闭包实现的。除函数之外,类也可以是 callable 对象,只要实现了__call__ 函数,偏函数其实也是 callable 对象。

3.1 实现

import time
import functools

# 延时类
class DelayFunc(object):
    def __init__(self,  duration, func):
        self.duration = duration
        self.func = func

    def __call__(self, *args, **kwargs):
        print(f'Wait for {self.duration} seconds...')
        time.sleep(self.duration)
        return self.func(*args, **kwargs)

    def eager_call(self, *args, **kwargs):
        print('Call without delay')
        return self.func(*args, **kwargs)

# 延时装饰器
def delay(duration):
    """
    装饰器:推迟某个函数的执行。
    同时提供 .eager_call 方法立即执行
    """
    # 此处为了避免定义额外函数,
    # 直接使用 functools.partial 帮助构造 DelayFunc 实例
    return functools.partial(DelayFunc, duration)

# 业务函数
@delay(duration=1)
def add(a, b):

    return a+b

if __name__ == "__main__":
    test_add = add(5, 6)
    print(test_add)
    print("add: {}".format(add))
    print("add.func: {}".format(add.func))
    print(">>>>>>>>>>>>>>>>>>>>")
    test_without_delay = add.eager_call(5, 5)
    print("test_without_delay: {}".format(test_without_delay))

3.2 运行结果

Wait for 1 seconds...
11
add: <__main__.DelayFunc object at 0x000001FD6763E668>
add.func: 
>>>>>>>>>>>>>>>>>>>>
Call without delay
test_without_delay: 10

Process finished with exit code 0

【Python】学点装饰器(2)_第1张图片
软件测试QA的碎碎念.jpg

你可能感兴趣的:(【Python】学点装饰器(2))