装饰器在调用它装饰的函数之前运行?
Posted
技术标签:
【中文标题】装饰器在调用它装饰的函数之前运行?【英文标题】:Decorators run before function it is decorating is called? 【发布时间】:2010-09-25 09:04:01 【问题描述】:举个例子:
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
甚至在我调用我正在装饰的函数之前就被调用了。
开始时输出:
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
此时我什至还没有调用装饰过的函数。
我刚刚开始使用装饰器,所以也许我遗漏了一些东西。
【问题讨论】:
直接回答问题标题,装饰器是否在被装饰函数之前运行?。不,声明函数时它不会运行。它在函数被调用时运行。我希望这会有所帮助。 【参考方案1】:我相信 python 装饰器只是语法糖。
@foo
def bar ():
pass
和
是一样的def bar ():
pass
bar = foo(bar)
如您所见,虽然 bar 没有被调用,但 foo 正在被调用。这就是为什么您会看到装饰器函数的输出。你的输出应该包含你应用装饰器的每个函数的一行。
【讨论】:
【参考方案2】:一旦定义了装饰函数,就会调用装饰器。相当于这样写:
def __do_stuff(...):
...
do_stuff = get_booking(__do_stuff)
【讨论】:
【参考方案3】:python 装饰器是应用于函数以对其进行转换的函数:
@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
【讨论】:
在装饰器中为目标函数提供默认值有什么好处? 特别是因为它从未检查过 None。 我真的不知道他的目的是什么,我以为是为了重定向。【参考方案4】:由于您是从装饰器开始的,我认为阅读这些内容会有所帮助,以便您提前了解陷阱和解决方法。
这里有两个链接指向之前关于装饰器的讨论。
Python decorator makes function forget that it belongs to a class What does functools.wraps do?
此外,第二个链接提到了“functools”一个用于高阶函数的模块,它作用于或返回其他函数。建议使用 functools.wraps ,因为它保留了原始函数的文档字符串(装饰过的)。
另一个问题是为我的项目生成自动文档时方法签名错误。 但有一个解决方法: Preserving signatures of decorated functions
希望这会有所帮助。
【讨论】:
以上是关于装饰器在调用它装饰的函数之前运行?的主要内容,如果未能解决你的问题,请参考以下文章