有时你需要在不改变源代码的情况下修改已经存在的函数。装饰器实质上是一个函数。它把一个函数作为输入并且返回另外一个函数。
       在装饰器中,通常使用下面这些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_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8

作为对前面人工装饰器赋值的替代,可以直接在要装饰的函数前添加装饰器名字@decoratoe_name:

@document_it
def add_ints(a, b):
  return a + b
>>> add_ints(3, 5)
Running function: add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8

同样一个函数可以有多个装饰器。

def square_it(func):
  def new_function(*args, **kwargs):
    result = func(*args, **kwargs)
    return result * result
  return new_function

靠近函数定义(def上面)的装饰器最先执行,然后依次执行上面的。任何顺序都会得到相同的最终结果。

@document_it
@square_it
def add_ints(a, b):
  return a + b
  
>>> add_ints(3, 5)
Running function: new_function
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 64
64
#交换两个装饰器的顺序:
@square_it
@document_it
def add_ints(a, b):
  return a + b
  
>>> add_ints(3, 5)
Running function: add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
64


摘抄自《Python语言及其应用》--装饰器