装饰器简介:
装饰器本质上是一个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))