Decorators
Steven D'Aprano
steve at pearwood.info
Fri Mar 6 09:46:21 EST 2009
Johny wrote:
> Hi,
> Can anyone explain to me what are decorators for? What are advantages
> of using them?
Decorators are for many things. One thing is for factoring out common
functionality. Suppose, for example, you have a number of functions that
all test that the argument is larger than zero. Here's two:
def spam(n):
if n <= 0:
raise ValueError("argument must be positive")
return "spam "*n
def spammier(n):
if n <= 0:
raise ValueError("argument must be positive")
return "spam spam wonderful SPAM "*n
Imagine you have lots of them. The common code is wasteful, tedious to type,
and it breaks the DRY principle ("Don't Repeat Yourself"). If you decide
that the functions need a different test, you have to change every single
function, which is prone to errors -- it's easy to miss one, or make a
mistake. So let's factor the common code out, using a decorator:
def test_argument(some_function):
# Decorator that checks that the argument to some_function is > 0.
def func(arg):
# The code common to all functions.
if n <= 0:
raise ValueError("argument must be positive")
# Now call the decorated function.
return some_function(arg)
return func
Notice that the decorator "test_argument" returns the function object "func"
itself, not the result of calling func().
Now let's see how to use it, first the old-fashioned way:
def spam(n):
return "spam "*n
spam = test_argument(spam)
This is so common that Python uses special syntax to simplify it.
@test_argument
def spammier(n):
return "spam spam wonderful SPAM "*n
Now if you need to change the test, say to ensure that n is at least five
instead of one, you can change it in a single place, inside the decorator.
--
Steven
More information about the Python-list
mailing list