举个例子,
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装饰器。
开始时的输出:
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
我甚至没有调用此时装饰的函数。
我刚刚开始使用装饰器,所以也许我错过了一些东西。有什么帮助吗?
答案 0 :(得分:32)
我相信python装饰器只是语法糖。
@foo
def bar ():
pass
与
相同def bar ():
pass
bar = foo(bar)
如您所见,即使未调用 bar ,也会调用 foo 。这就是你看到装饰器功能的输出的原因。对于应用装饰器的每个函数,您的输出应该包含一行。
答案 1 :(得分:2)
由于你是从装饰者开始的,我认为阅读这些装置会很有帮助,所以你事先就知道了陷阱和变通方法。
以下是关于装饰器的早期讨论的两个链接。
Python decorator makes function forget that it belongs to a class What does functools.wraps do?
此外,第二个链接提到'functools'是一个用于高阶函数的模块,它可以作用于或返回其他函数。建议使用functools.wraps,因为它保留了原始函数的doc字符串(装饰一个)。
另一个问题是在为我的项目生成自动文档时错误的方法签名。 但有一个解决方法: Preserving signatures of decorated functions
希望这有帮助。
答案 2 :(得分:0)
定义修饰函数后立即调用装饰器。这相当于写下这样的东西:
def __do_stuff(...):
...
do_stuff = get_booking(__do_stuff)
答案 3 :(得分:0)
python decorators是应用于函数的函数,用于转换它:
@my_decorator
def function (): ...
就像这样:
def function():...
function = my_decorator(function)
您想要做的是:
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