[Tutor] basic decorator question
steve at pearwood.info
Mon Jul 24 12:01:30 EDT 2017
On Mon, Jul 24, 2017 at 10:33:25AM -0400, bruce wrote:
> I've seen sites discuss decorators, as functions that "wrap" and
> return functions.
> But, I'm sooo confuzed! My real question though, can a decorator have
> multiple internal functions? All the examples I've seen so far have a
> single internal function.
Yes, a decorator can have multiple internal functions. A decorator is
just a function, and it can contain anything a function contains. What
makes it specifically a decorator is what you use it for.
Let's step back and cover a basic: nested functions.
return x + 1
return (add_one(), times_two())
Can you predict what the result of that will be? I hope you can predict
that it will return (11, 20). Can you see why?
That sort of nested function isn't very interesting, and you won't see
much code doing that. But it demonstrates that a function can contain
multiple inner functions. Now let's look at something that is often
called a *factory function* -- a function which creates and returns a
return a + x
return inner # No parentheses!
add_one = factory(1) # create a new function & assign it to add_one
add_two = factory(2)
add_one(100) # returns 101
add_two(100) # returns 102
How this works isn't important (the technical term is "a closure") but
the important factor is this: factory() creates a new function, and
returns it. That function can then be used like any other function
created with "def".
Functions can not only *return* functions as their return result, but
they can take functions as arguments. We say that "functions are first
class values" -- in Python, functions are just another kind of data,
like ints, floats, strings, lists, dicts and more. The most common
examples of passing a function as input to another function include:
- builtin functions map() and reduce();
- the key argument to sorted() and list.sort();
- GUI libraries that take callback functions;
- and of course, decorators.
So let's start to create our first decorator. A decorator takes a
function as argument, "decorates" it in some way (usually by adding some
sort of extra functionality), and then returns the decorated function.
Here's a simple example: a decorator that makes the other function print
print('received argument %r' % arg)
Now let's set up a couple of functions:
And decorate them:
add_five = decorate(add_five)
add_ten = decorate(add_ten)
Try predicting what
result = add_five(100)
will print, and what the result will be. Likewise for:
result = add_ten(50)
Try running the code and see if you are correct.
The way I decorated the functions above is a little bit clumsy, so
Python has a special syntax to make it easier: the "@decorate" syntax.
result = times_three(5)
Can you predict what that will do?
There's more to decorators than that, but hopefully that will
demonstrate some of the basic concepts. Feel free to ask any more
questions on the mailing list, and we will answer if we can.
More information about the Tutor