function decorators

Diez B. Roggisch deets at web.de
Wed Sep 29 00:24:45 CEST 2010


Nick Donohue <ndonohue at gmail.com> writes:

> I came across this code just now:
>
> def time_me(function):
>   def wrap(*arg):
>     start = time.time()
>     r = function(*arg)
>     end = time.time()
>     print "%s (%0.3f ms)" %(function.func_name, (end-start)*1000)
>   return wrap
>
> @time_me
> def some_function(somearg)
>
> some_function(arg)
>
> I've been looking online about what I think is going on, and from what
> I can tell this code is using function decorators.
>
> I guess what I'm asking is if someone could tell me what exactly is
> going on in this code - how is it different from passing:
> time_me(some_function(123))? I've tried it this way and it works.

This is *not* what the decorator is doing. The equivalent of a decorator
and then calling the result is this:

>>> some_function = time_me(some_function)
>>> some_function(123)

Notice the difference? The decorator (a badly written one, by the way -
it doesn't deal with a possible return value and keyword args) wraps the function
into time measuring code. 

In general, a decorator is a callable that takes one argument. And
whatever that callable returns is then bound under the same name as the
original function (or class, since python 2.6 I believe)

Which is what 

>>> some_function = time_me(some_function)

actually does. So decorator syntax with the @ is really just that - a
bit of syntactic sugar.


> why would I use these? wouldn't it be more flexible to not write the
> decorator before the function definition, so I could choose to wrap it
> or not?

Of course it's more flexible to do whatever the decorator does only if
you need it. If you need that, it's a sign of a misuse of decorators.

Their strength is in making boiler-plate code run without you having to
type it out all the time.

E.g. putting transactional boundaries around some code that deals with a
database. Checking for proper authentication and
authorization. Uniformely deal with exceptions. And so forth.

Amongst the more popular decorators in python are the classmethod and
property decorators. Go look them up in the stdlib.


Diez



More information about the Python-list mailing list