我对Python很新,并且一直在学习装饰器。在搞乱Flask之后,我正在尝试编写一些模拟其路由处理程序/装饰器的代码,只是为了理解装饰器(带参数)是如何工作的。
在下面的代码中,路径装饰器似乎在脚本运行后调用自身。我的问题是,当我运行这个脚本时,app.route()
怎么可能被调用,这里真的发生了什么?请注意,我不会直接在任何地方调用index()
函数。
# test.py
class Flask(object):
def __init__(self, name):
self.scriptname = name
def route(self, *rargs, **kargs):
args = list(rargs)
if kargs:
print(kargs['methods'])
def decorator(f):
f(args[0])
return decorator
app = Flask(__name__)
@app.route("/", methods = ["GET","PUT"])
def index(rt):
print('route: ' + rt)
以上在我的终端中打印出来:
$ python test.py
['GET', 'PUT']
route: /
任何见解都将受到赞赏。
答案 0 :(得分:2)
@app.route("/", methods = ["GET","PUT"])
是一个可执行语句:它调用app对象的route()
方法。由于它是在模块级别,因此将在导入脚本时执行。
现在,调用app.route(...)
的结果是一个函数,因为你已经使用@
将它标记为装饰器,该函数将包装{{ 1}}。请注意,语法只是一个快捷方式:
index
换句话说,Python将index = app.route(...)(index)
返回的函数作为参数调用,并将结果存储为新的app.route()
函数。
然而,你在这里错过了一个级别。没有params的普通装饰器是这样写的:
index
并且导入模块时,运行index
并返回包装@foo
def bar()
pass
的函数。但是你在装饰者的电话中调用你的foo()
函数 !所以实际上你的函数需要返回一个装饰器函数,它本身返回一个包装原始函数的函数... headscratching,确定。
您的bar
方法应该更像这样:
route()
答案 1 :(得分:-1)
基本上...... app.route(index, "/", ["GET", "PUT"])
是一个功能。这是将被调用而不是索引的函数。
在您的代码中,当您致电index()
时,它会调用app.route(index, "/", ["GET", "PUT"])
。首先打印kargs['methods']
,然后创建装饰器功能:
def decorator(f):
f(args[0])
此装饰器将使用一个参数f
调用装饰函数(args[0]
),此处为“/”。这会打印route: /
。
我找到的装饰者的最佳解释是:How to make a chain of function decorators?
如果您不想自我解雇,可以这样定义装饰器:
def route(*rargs, **kargs):
args = list(rargs)
if kargs:
print(kargs['methods'])
def decorator(f):
f(args[0])
return decorator
@app.route("/", methods = ["GET","PUT"])
def index(rt):
print('route: ' + rt)
但是,永远不会使用索引的rt
参数,因为route
始终使用index
调用args[0]
,\
始终为{{1}} ... < / p>