Reputation:
I am having a hard time grasping decorators, I initially thought decorators were syntactic sugar to do an operation such as:
def decorator(x):
return x*2
@decorator
def plusone(x):
return x+1
print plusone(5)
# would print twelve, because: decorator(plusone(5)) as I have seen
# in some tutorials
but I've noticed that a wrapper function needs to be created in the decorator first.
Why do we need to return a function, not an integer?
Upvotes: 0
Views: 1221
Reputation: 76297
A (Python) decorator is syntactic sugar for a function modifying a function, causing the latter function to act like a modified version of itself.
Let's start with a simple (and not so good) example. Say we write
def double_me(f):
return lambda x: 2 * f(x)
which takes a function taking one parameter, and returns a function taking one parameter and returning double what the original function would return. Then we can use it like this:
def double_the_add_one(x):
return x + 1
double_the_add_one = double_me(double_the_add_one)
>>> double_the_add_one(1)
4
Note that we first defined double_the_add_one
, then modified double_the_add_one
and bound it back to double_the_add_one
. So now it is just a modified version of itself - it does what it would do originally, then just doubles the result. Decorators simply make this a bit more succinct:
@double_me
def double_the_add_one(x):
return x + 1
>>> double_the_add_one(1)
4
Note that the above decorator wasn't that great:
It assumed there was a single positional argument.
It assumed there were no keyword arguments.
If the decorated function had a docstring, it was clobbered.
You should probably use functools.wraps
to actually write decorators using the example in the docs there.
Upvotes: 3