Python 语言及其应用 Chapter_4_Note_4 装饰器

来源:互联网 发布:淘宝网李宁 编辑:程序博客网 时间:2024/05/16 07:36

又到难搞的项目了

先做笔记,有点搞脑子啊,烧脑...............

有时你需要在不改变源代码的情况下修改已经存在的函数。常见的例子是增加一句调试声
明,以查看传入的参数。
装饰器实质上是一个函数。它把一个函数作为输入并且返回另外一个函数。在装饰器中,
通常使用下面这些Python 技巧:
• *args 和**kwargs
• 闭包
• 作为参数的函数
函数document_it() 定义了一个装饰器,会实现如下功能:
• 打印输出函数的名字和参数的值
• 执行含有参数的函数
• 打印输出结果
• 返回修改后的函数
看下面的代码:
>>> def document_it(func):
... def new_function(*args, **kwargs):

... print('Running function:', func.__name__)
... print('Positional arguments:', args)
... print('Keyword arguments:', kwargs)
... result = func(*args, **kwargs)
... print('Result:', result)
... return result
... return new_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
Postitional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8


作为对前面人工装饰器赋值的替代, 可以直接在要装饰的函数前添加装饰器名字
@decorator_name:
>>> @document_it
... def add_ints(a, b):
... return a + b
...
>>> add_ints(3, 5)
Start function add_ints
Positional arguments: (3, 5)
Keyword arguments: {}
Result: 8
8
同样一个函数可以有多个装饰器。下面,我们写一个对结果求平方的装饰器square_it():
>>> def square_it(func):
... def new_function(*args, **kwargs):
... result = func(*args, **kwargs)
... return result * result
... return new_function
...
靠近函数定义(def 上面)的装饰器最先执行,然后依次执行上面的。任何顺序都会得到
相同的最终结果
。下面的例子中会看到中间步骤的变化:

>>> @document_it                #再执行这个装饰器 , 这个装饰器有打印内容的语句,所以结果里面输出的内容是这个装饰器打印的
... @square_it                        #先执行这个装饰器,这个装饰器内并没有打印出什么的语句,只是return一些数据供其他地方使用
... 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:                              #因为先执行document这个装饰器,所以打印语句的时候,结果还是执行加法时候的结果,虽然整个大程序最后的结果是一样的。
64




0 0
原创粉丝点击