装饰器是用于调用高阶函数的特定方法的简单语法,因此如果您只关注语法,则不太可能产生很大的差异.IOW,无论你在哪里说
@mydecorator
def f(...):
# body of f
Run Code Online (Sandbox Code Playgroud)
你可以这么说
def f(...):
# body of f
f = mydecorator(f)
Run Code Online (Sandbox Code Playgroud)
该装饰语法的优势是,它更简洁的一丁点(无重复f三次;-)并谈到之前的def(或者class,类装饰)语句,这样就会立即提醒代码的阅读器.这很重要,但它不会很棒!
装饰器的语义(以及相同的,与此模式匹配的高阶函数调用,如果没有装饰器;-).例如,
@classmethod
def f(cls, ...):
Run Code Online (Sandbox Code Playgroud)
让你创建类方法(对备用构造函数非常有用),以及
@property
def foo(self, ...):
Run Code Online (Sandbox Code Playgroud)
允许你创建只读属性(2.6中的其他相关装饰器用于非只读属性;-),即使不使用它们也非常有用(因为它们可以避免你编写很多愚蠢的"样板"访问器本质上属性...只是因为访问属性可能需要在将来触发一些计算! - ).
除了内置于Python中的内容之外,您自己的装饰器也同样重要 - 当然,这取决于您的应用程序.通常,它们可以很容易地重构代码的某些部分(否则必须在许多函数和类中重复[[或者你可能不得不求助于类的情况,但是那些更丰富,更复杂到正确使用]])进入装饰器.因此,它们可以帮助您避免重复的样板代码 - 而且,因为DRY,"不要重复自己",这是软件开发的核心原则,所以您应该得到的任何帮助都应该受到热烈欢迎.
了解装饰器有用性的最简单方法是查看一些示例。例如,这是一个:
假设您正在研究一些代码并希望了解函数何时以及如何被调用。您可以使用装饰器来更改函数,以便每次调用该函数时都会打印一些调试信息:
import functools
def trace(f):
'''This decorator shows how the function was called'''
@functools.wraps(f)
def wrapper(*arg,**kw):
arg_str=','.join(['%r'%a for a in arg]+['%s=%s'%(key,kw[key]) for key in kw])
print "%s(%s)" % (f.__name__, arg_str)
return f(*arg, **kw)
return wrapper
@trace
def foo(*args):
pass
for n in range(3):
foo(n)
Run Code Online (Sandbox Code Playgroud)
印刷:
# foo(0)
# foo(1)
# foo(2)
Run Code Online (Sandbox Code Playgroud)
如果您只想跟踪一个函数foo,您当然可以将代码更简单地添加到以下定义中foo:
def foo(*args):
print('foo({0})'.format(args))
Run Code Online (Sandbox Code Playgroud)
但是如果您有许多想要跟踪的函数,或者不想弄乱原始代码,那么装饰器就会变得有用。
有关有用装饰器的其他示例,请参阅装饰器库。