user3434449
user3434449

Reputation:

python decorators and wrappers

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

Answers (1)

Ami Tavory
Ami Tavory

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:

  1. It assumed there was a single positional argument.

  2. It assumed there were no keyword arguments.

  3. 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

Related Questions