关于django:Python装饰器在它正在装饰的函数之前运行吗?

Python Decorators run before function it is decorating is called?

举个例子,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

我遇到的问题是,@get_booking decorator正在被调用,甚至在调用我正在装饰的函数之前。

启动时输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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

我甚至还没有调用在这一点上被修饰的函数。

我刚开始装修,所以可能我错过了一些东西。有什么帮助吗?


我相信python修饰器只是语法上的糖分。

1
2
3
@foo
def bar ():
    pass

1
2
3
def bar ():
    pass
bar = foo(bar)

正如你所看到的,即使酒吧还没有被调用,FOO也在被调用。这就是您看到decorator函数输出的原因。对于您应用了修饰符的每个函数,您的输出应该包含一行。


既然你是从装饰师开始的,我认为阅读这些会很有帮助,这样你就可以事先知道缺陷和解决方法。

这里有两个链接指向之前关于装饰师的讨论。

python decorator使函数忘记它属于一个类functools.wrapps做什么?

此外,第二个链接提到了"functools"模块,它是用于执行或返回其他函数的高阶函数。建议使用functools.wrapps,因为它保留了原始函数(修饰函数)的文档字符串。

另一个问题是为我的项目生成自动文档时方法签名错误。但有一个解决办法:保留修饰函数的签名

希望这有帮助。


python decorator是应用于函数以转换它的函数:

1
2
@my_decorator
def function (): ...

就像这样:

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

你想做的是:

1
2
3
4
5
6
7
8
9
10
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


一旦定义了修饰函数,就会调用decorator。它相当于写这样的东西:

1
2
3
4
def __do_stuff(...):
    ...

do_stuff = get_booking(__do_stuff)