装饰器如何标记一个函数?
How do decorators mark a function?
我正在阅读具有以下代码的基本 Flask 教程:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
我还从许多网站上学习了 Python 装饰器的基础知识,包括 Whosebug Decorators
我假设在前面的代码中,函数 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()
在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
装饰器实际上是 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
请注意,这几乎是 link Jon Piparsky provided.
中给出的解释的浓缩版
装饰器只是在查找中注册函数 table。装饰器不需要以任何方式修改函数,装饰器可以做很多其他有用的事情。
事实上,python
中的装饰器
@some_decorator
def foo():
pass
只是
的缩写形式
def foo():
pass
foo = some_decorator(foo)
和函数 some_decorator
可以用它的参数做任何事情,并且可以 return 任何 return 值,但通常 return 是一个函数。
我正在阅读具有以下代码的基本 Flask 教程:
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()
我还从许多网站上学习了 Python 装饰器的基础知识,包括 Whosebug Decorators
我假设在前面的代码中,函数 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()
在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
装饰器实际上是 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
请注意,这几乎是 link Jon Piparsky provided.
中给出的解释的浓缩版装饰器只是在查找中注册函数 table。装饰器不需要以任何方式修改函数,装饰器可以做很多其他有用的事情。
事实上,python
中的装饰器@some_decorator
def foo():
pass
只是
的缩写形式def foo():
pass
foo = some_decorator(foo)
和函数 some_decorator
可以用它的参数做任何事情,并且可以 return 任何 return 值,但通常 return 是一个函数。