繁体   English   中英

Python装饰器自燃

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM