有时你需要在不改变源代码的情况下修改已经存在的函数。装饰器实质上是一个函数。它把一个函数作为输入并且返回另外一个函数。

       在装饰器中,通常使用下面这些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语言及其应用》--装饰器