有时你需要在不改变源代码的情况下修改已经存在的函数。装饰器实质上是一个函数。它把一个函数作为输入并且返回另外一个函数。
在装饰器中,通常使用下面这些Python技巧:*args和**kwargs
闭包
作为参数的函数
函数document_it()定义了一个装饰器,会实现如下功能:
打印输出函数的名字和参数的值
执行含有参数的函数
打印输出结果
返回修改后的函数
def documet_it(func): def new_function(*args, **kwargs): print('Running function:', func.__name__) print('Positonal arguments:', args) print('Keyword arguments:', kwargs) result = func(*args, **kwargs) print('Result:', result) return result return nes_function
无论传入document_it()的函数func是什么,装饰器都会返回一个新的函数,其中包含函数document_it()增加的额外语句。实际上,装饰器并不需要执行函数func中的代码,只是在结束前函数document_it()调用函数func以便得到func的返回结果和附加代码的结果。
那么,如何使用装饰器?当然,可以通过人工赋值:def add_ints(a, b): return a + b>>> add_ints(3, 5)8>>> cooler_add_ints = document_it(add_ints) #人工对装饰器赋值>>> cooler_add_ints(3, 5)Running function: add_intsPositional arguments: (3, 5)Keyword arguments: {}Result: 88
作为对前面人工装饰器赋值的替代,可以直接在要装饰的函数前添加装饰器名字@decoratoe_name:
@document_itdef add_ints(a, b): return a + b>>> add_ints(3, 5)Running function: add_intsPositional arguments: (3, 5)Keyword arguments: {}Result: 88
同样一个函数可以有多个装饰器。
def square_it(func): def new_function(*args, **kwargs): result = func(*args, **kwargs) return result * result return new_function
靠近函数定义(def上面)的装饰器最先执行,然后依次执行上面的。任何顺序都会得到相同的最终结果。
@document_it@square_itdef add_ints(a, b): return a + b >>> add_ints(3, 5)Running function: new_functionPositional arguments: (3, 5)Keyword arguments: {}Result: 6464#交换两个装饰器的顺序:@square_it@document_itdef add_ints(a, b): return a + b >>> add_ints(3, 5)Running function: add_intsPositional arguments: (3, 5)Keyword arguments: {}Result: 864
摘抄自《Python语言及其应用》--装饰器