我正在阅读基本的Flask教程,其中包含以下代码:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
此外,我还从许多网站(包括Stackoverflow Decorators
)了解了Python装饰器的基础知识我假设在前面的代码中,函数hello
将被更改和修饰,并且为了运行应用程序,我需要在某处调用函数hello()
。 Flask如何确定它必须调用的函数的名称。
只是用装饰器包装函数定义会以某种方式标记该函数吗?如果是这样,怎么样?
例如,在下面的代码中,我在某处的某个地方调用了我装饰的功能:
def decorate(foo):
print("I'm doing a lot of important stuff right now")
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
return inner
@decorate
def hello():
print("Hello")
hello()
答案 0 :(得分:4)
在decorate
中,foo
是您要装饰的功能(在本例中为hello
)。您可以将函数存储在某个列表或字典中,因为它是一个普通对象。
例如:
decorated_functions = []
def decorate(foo):
def inner():
print("Some stuff 1")
foo()
print("Some stuff 2")
decorated_functions.append(inner)
return inner
@decorate
def hello():
print("Hello")
## The above is the same as:
# def hello():
# print("Hello")
# hello = decorate(hello)
print(decorated_functions[0] == hello) # prints True
decorated_functions[0]() # prints "Some stuff 1", "Hello", and "Some stuff 2"
hello() # same as above
答案 1 :(得分:1)
装饰器实际上是Python中非常简单的构造。以下两个例子是等效的:
@foo
def bar():
pass
def bar():
pass
bar = foo(bar)
因此,您在第一个示例中对hello
的定义与此相当:
def hello():
return "Hello World!"
hello = app.route("/")(hello)
双重函数调用可能有点令人困惑,所以让我们像这样重写:
_tempfn = app.route("/")
hello = _tempfn(hello)
所以现在应该很清楚app.route
实际上并不是装饰器,它是创建装饰器的函数。现在不明显的是新装饰者做了什么。如果不查看Flash的来源,可能会将函数hello
添加到app
的字典成员中。所以app.route
的实现方式如下:
class app(object):
def route(self, path):
def decorator(fn):
self.pathmap[path] = fn
return fn
return decorator
请注意,这几乎是Jon Piparsky provided链接中给出的解释的精简版本。
答案 2 :(得分:1)
装饰器只是在查找表中注册该函数。装饰者不需要以任何方式修改函数,装饰者可以做很多其他有用的事情。
实际上,python中的装饰器
@some_decorator
def foo():
pass
只是
的简短形式def foo():
pass
foo = some_decorator(foo)
并且函数some_decorator
可以对其参数执行任何操作,并且可以返回任何返回值,但通常会返回一个函数。