Question

As an example,

def get_booking(f=None):
    print "Calling get_booking Decorator"
    def wrapper(request, **kwargs):
        booking = _get_booking_from_session(request)
        if booking == None:
            # we don't have a booking in our session.
            return HttpRedirect('/')
        else:
            return f(request=request, booking=booking, **kwargs)
    return wrapper

@get_booking
def do_stuff(request, booking):
    # do stuff here

The problem I am having is, the @get_booking decorator is being called even before I called the function that I am decorating.

Output on start:

Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
Calling get_booking Decorator
[26/Oct/2008 19:54:04] "GET /onlinebooking/?id=1,2 HTTP/1.1" 302 0
[26/Oct/2008 19:54:05] "GET /onlinebooking/ HTTP/1.1" 200 2300
[26/Oct/2008 19:54:05] "GET /site-media/css/style.css HTTP/1.1" 200 800
[26/Oct/2008 19:54:05] "GET /site-media/css/jquery-ui-themeroller.css HTTP/1.1" 200 25492

I haven't even made a call to a function that is decorated at this point.

I am just getting started with decorators, so maybe I am missing something. Any help?

Was it helpful?

Solution

I believe python decorators are just syntactic sugar.

@foo
def bar ():
    pass

is the same thing as

def bar ():
    pass
bar = foo(bar)

As you can see, foo is being called even though bar has not been called. This is why you see the output from your decorator function. Your output should contain a single line for every function you applied your decorator to.

OTHER TIPS

Since you are starting with decorators, I think reading these will be helpful, so that you know the pitfalls and workarounds beforehand.

Here are two links to earlier discussions on decorators.

Python decorator makes function forget that it belongs to a class What does functools.wraps do?

Moreover the second link mentions 'functools' a module for higher-order functions, that act on or return other functions. Use of functools.wraps is advised since it preserves the doc string of the original function(decorated one).

Another issue was wrong method signatures while generating automatic docs for my project. but there is a workaround: Preserving signatures of decorated functions

Hope this helps.

A decorator is called as soon as the decorated function is defined. It is equivalent to writing something like this:

def __do_stuff(...):
    ...

do_stuff = get_booking(__do_stuff)

python decorators are functions applied to a function to transform it:

@my_decorator
def function (): ...

is like doing this:

def function():...
function = my_decorator(function)

What you want to do is:

def get_booking(f=None):
    def wrapper(request, **kwargs):
        print "Calling get_booking Decorator"
        booking = _get_booking_from_session(request)
        if booking == None:
            # we don't have a booking in our session.
            return HttpRedirect('/')
        else:
            return f(request=request, booking=booking, **kwargs)
    return wrapper
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top