共计 1900 个字符,预计需要花费 5 分钟才能阅读完成。
目录 | 上一节 (7.3 返回函数) | [下一节 (7.5 装璜办法)]()
7.4 函数装璜器
本节介绍装璜器(decorator)。因为这是一个高级主题,所以咱们只做简略介绍。
译注:依据译者集体的猜想,在《设计模式》(《Design Patterns: Elements of Reusable Object-Oriented Software》)一书中写到 decorator also known as wrapper
,所以下文提到包装器(wrapper),其实说的就是装璜器。这里为了放弃和原文统一,所以翻译的时候没有将“包装器”替换为“装璜器”。
日志示例
思考这样一个函数:
def add(x, y):
return x + y
思考给 add(x, y)
函数增加日志性能:
def add(x, y):
print('Calling add')
return x + y
也带有日志性能的 sub(x, y)
函数:
def sub(x, y):
print('Calling sub')
return x - y
察看
察看:这是一种反复。
在有大量反复代码的中央编写程序通常很烦人。这些代码不仅写起来干燥,保护起来也很麻烦。尤其是你决定更改其工作形式的时候(例如,可能是另一种类型的日志记录)。
记录日志的代码
兴许你能够创立一个增加了日志性能的函数。例如包装器(wrapper):
def logged(func):
def wrapper(*args, **kwargs):
print('Calling', func.__name__)
return func(*args, **kwargs)
return wrapper
应用该函数:
def add(x, y):
return x + y
logged_add = logged(add)
当调用 logged
返回的函数时会产生什么?
logged_add(3, 4) # You see the logging message appear
此示例说明了创立所谓的 包装器函数(wrapper function) 的过程。
包装器是一个函数,它包装了另一个带有额定解决性能的函数,但在其它方面与原始函数的工作形式完全相同。
>>> logged_add(3, 4)
Calling add # Extra output. Added by the wrapper
7
>>>
注意事项:logged()
函数创立了一个包装器,并作为后果返回。
装璜器
在 Python 中,在函数中应用包装器十分常见。因为如此广泛,所以有一个非凡的语法。
def add(x, y):
return x + y
add = logged(add)
# Special syntax
@logged
def add(x, y):
return x + y
该非凡语法执行与下面完全相同的确切步骤。装璜器只是一种新语法,用于装璜函数。
阐明
对于装璜器而言,还有许多比这里展现的更奥妙的细节,例如,在类外面应用装璜器,或者对同一个函数应用多个装璜器。不过,这里的例子曾经很好地阐明了如何应用它们。一般而言,它是对呈现在各种函数定义中的反复代码的响应。装璜器能够将反复代码移至核心定义。
练习
练习 7.10:计时装璜器
如果你定义了一个函数,那么函数的名称和函数所属模块的名称会别离存储到 __name__
和 __module__
属性中。示例:
>>> def add(x,y):
return x+y
>>> add.__name__
'add'
>>> add.__module__
'__main__'
>>>
请创立 timethis.py
文件,并在文件中编写 timethis(func)
函数。timethis(func)
函数包装一个具备额定逻辑层的函数,逻辑层打印出函数执行所须要的事件。为此,你将在函数中增加如下计时调用。
start = time.time()
r = func(*args,**kwargs)
end = time.time()
print('%s.%s: %f' % (func.__module__, func.__name__, end-start))
(timethis(func)
)装璜器工作形式示例:
>>> from timethis import timethis
>>> @timethis
def countdown(n):
while n > 0:
n -= 1
>>> countdown(10000000)
__main__.countdown : 0.076562
>>>
探讨:@timethis
装璜器能够放在任何函数的后面,即你应该把装璜器用作性能调优(performance tuning)的诊断工具。
目录 | 上一节 (7.3 返回函数) | [下一节 (7.5 装璜办法)]()
注:残缺翻译见 https://github.com/codists/practical-python-zh