[英]Python Decorator Self-firing
我对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: /
任何见识将不胜感激。
@app.route("/", methods = ["GET","PUT"])
是一个可执行语句:它调用应用程序对象的route()
方法。 由于它是在模块级别,因此将在导入脚本时执行。
现在,调用app.route(...)
的结果是一个函数,并且因为您已使用@
将其标记为装饰器,所以该函数将包装index
。 请注意,语法只是为此的快捷方式:
index = app.route(...)(index)
换句话说,Python将使用index
作为参数调用app.route()
返回的函数,并将结果存储为新的index
函数。
但是,您在这里缺少一个级别。 没有参数的普通装饰器的编写方式如下:
@foo
def bar()
pass
当导入模块时,将运行foo()
并返回包装bar
的函数。 但你打电话给你route()
的调用装饰函数内 ! 因此,实际上,您的函数需要返回一个装饰器函数 , 该装饰器函数本身将返回一个包装原始函数的函数……可以肯定的。
您的route
方法应如下所示:
def route(self, *rargs, **kargs):
args = list(rargs)
if kargs:
print(kargs['methods'])
def decorator(f):
def wrapped(index_args):
f(args[0])
return wrapped
return decorator
基本上... app.route(index, "/", ["GET", "PUT"])
是一个函数。 这就是将要调用的函数而不是索引。
在您的代码中,当您调用index()
,它将调用app.route(index, "/", ["GET", "PUT"])
。 首先打印kargs['methods']
,然后创建装饰器函数:
def decorator(f):
f(args[0])
该修饰器将使用一个参数args[0]
调用修饰的函数( f
),此处为“ /”。 这将打印route: /
。
我发现的装饰器的最佳解释是: 如何制作功能装饰器链?
如果您不希望自行点火,则可以通过以下方式定义装饰器:
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)
但是,永远不会使用index的rt
参数,因为route
总是使用args[0]
来调用index
,而args[0]
总是\\
...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.