Python装饰器详解

装饰器简介:

  装饰器本质上是一个Python函数,它可以让其他函数在不需要做任何代码变动的前提下增加额外功能,装饰器的返回值也是一个函数对象。它经常用于有切面需求的场景,比如:插入日志、性能测试、事务处理、缓存、权限校验等场景。装饰器是解决这类问题的绝佳设计,有了装饰器,我们就可以抽离出大量与函数功能本身无关的雷同代码并继续重用。

一个简单装饰器写法:

  在写装饰器之前我们需要简单了解下python语法糖@的用法 http://www.cnblogs.com/Egbertbaron/p/7242515.html 

def debug(func):
    def wrapper():
        print("[DEBUG]: enter {}()".format(func.__name__))  # 输出原函数名字
        return func()
    return wrapper()  # 回调包装过的函数

@debug
def say_hello():
    print("Hello world!")

运行结果:
[DEBUG]: enter say_hello()
Hello world!

   以上代码就实现了一个简单的装饰器。他对原函数进行了包装并返回了另一个函数,额外添加了一个输出原函数名字的功能,但是这样做有一个问题,那就是原函数 say_hello() 不能就行传参,并且返回的函数 wrapper() 也并不能接受参数,所以我们这个代码还得进一步的完善。例如:

def debug(func):
    def wrapper(something):  # 指定和原函数一模一样的参数
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func(something)
    return wrapper  # 回调包装过的函数

@debug
def say_hello(something):
    print("Hello world!{}".format(something))

say_hello('Mr.hou')  # 给原函数传一个参数

运行结果:
[DEBUG]: enter say_hello()
Hello world!Mr.hou

  刚解决了传参数问题,得!新问题又来了!那么多的函数每个函数又都有自己函数,包装函数有可能把没函数的参数添加进去,所以我们在这里有可以用到python提供的 可变参数*args 和 关键字参数**kwargs (这里有关于 *args 和 **kwargs 的介绍http://www.cnblogs.com/Egbertbaron/p/7242515.html),有了这俩参数,装饰器就可以用于带任意参数目标函数了。修改后的代码如下:

def debug(func):
    def wrapper(*args, **kwargs):  # 把指定参数变为可变参数和关键字参数
        print("[DEBUG]: enter {}()".format(func.__name__))
        return func(*args, **kwargs)
    return wrapper  # 回调包装过的函数

@debug
def say_hello(something):
    print("Hello world!{}".format(something))
原文地址:https://www.cnblogs.com/Egbertbaron/p/7242445.html