function decorators

Discussion in 'Python' started by Nick Donohue, Sep 28, 2010.

  1. Nick Donohue

    Nick Donohue Guest

    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.

    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?

    thanks
     
    Nick Donohue, Sep 28, 2010
    #1
    1. Advertising

  2. Nick Donohue

    Seebs Guest

    On 2010-09-28, Nick Donohue <> wrote:
    > 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?


    The utility is that it lets you modify all calls to a function at once,
    without changing all the instances in a ton of source code.

    -s
    --
    Copyright 2010, all wrongs reversed. Peter Seebach /
    http://www.seebs.net/log/ <-- lawsuits, religion, and funny pictures
    http://en.wikipedia.org/wiki/Fair_Game_(Scientology) <-- get educated!
    I am not speaking for my employer, although they do rent some of my opinions.
     
    Seebs, Sep 28, 2010
    #2
    1. Advertising

  3. Nick Donohue <> 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
     
    Diez B. Roggisch, Sep 28, 2010
    #3
  4. Nick Donohue

    Terry Reedy Guest

    On 9/28/2010 6:02 PM, Nick Donohue wrote:
    > 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)


    As others noted, this is an bad example of a decorator. Please forget
    it. Let us move on...

    #deco
    def func_name(*args): pass

    is syntactic sugar for (which is to say, is almost and for practical
    purposes is exactly equivalent to)

    def func_name(*args): pass
    func_name = deco(func_name)

    Indeed, Python did well without them until they were added. But there
    are 2 advantages of the decorator syntax:

    1. Without it, one write (and read!) func_name 3 times instead of 1. One
    of the use cases that motivated decorators was a situation where someone
    was required to wrap numerous functions with stylized names about 30
    chars long, like 'get_hopscotch_version_a_code_123x76'

    2. Understanding the code may require that one know that it will never
    see the light of day as is. If the body is several lines, the wrapping
    call may be hard to see. To put it another way, the wrapping calls often
    belong near the doc string since they are part of a high-level overview
    of the function.

    --
    Terry Jan Reedy
     
    Terry Reedy, Sep 29, 2010
    #4
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Arien Malec

    PEP 318 decorators are not Decorators

    Arien Malec, Aug 13, 2004, in forum: Python
    Replies:
    11
    Views:
    579
    Arien Malec
    Aug 16, 2004
  2. Porky Pig Jr
    Replies:
    0
    Views:
    268
    Porky Pig Jr
    Aug 14, 2004
  3. Bengt Richter
    Replies:
    0
    Views:
    300
    Bengt Richter
    Aug 25, 2004
  4. Replies:
    5
    Views:
    300
  5. Vedran

    Decorators without function

    Vedran, Aug 9, 2010, in forum: Python
    Replies:
    2
    Views:
    231
    Gregory Ewing
    Aug 10, 2010
Loading...

Share This Page