python装饰器进阶

为什么要使用?

使用装饰器使代码变得整洁,并且能解决硬编码问题,使用起来也很方便,但是理解起来相对没那么容易,因此写下这篇文章加深理解。下面以记录日志的功能作为装饰器的讲解:

原始硬编码版

下面的logit作为装饰器,但是它只能装饰有两个参数的函数,因此是硬编码的。

def logit(func):
    def decorator(a, b):
        print("func %s is calling " % func.__name__)
        return func(a, b)
    return decorator

@logit()
def my_add(a, b):
    return a+b
  
my_add(1, 49)

可变参数版

使用*args, **kwargs将上述的硬编码去除,使得装饰器能装饰不同的函数

def logit(func):
    def decorator(*args, **kwargs):
        print("func %s is calling " % func.__name__)
        return func(*args)
    return decorator

wraps通用版

输出my_add.name发现函数的名称改变了,不是我们想要的my_add,因此使用wraps改造

print(my_add.__name__)
from functools import wraps
def logit(func):
    @wraps(func)
    def decorator(*args, **kwargs):
        print("func %s is calling " % func.__name__)
        return func(*args)
    return decorator

自定义参数版

有时候需要向装饰器来传递参数,例如不同的函数需要不同的日志文件时:

def logit(log_name="add.log"):
    def decorator(func)
        @wraps(func)
        def wrapper(*args, **kwargs):
            log_str = "func %s is calling " % func.__name__
            print(log_str)
            with open(log_name, "a") as log_file:
              log_file.write(log_str)
            return func(*args)
        return wrapper
    return decorator

你可能感兴趣的:(python装饰器进阶)