装饰函数如何在flask/python中工作?(app.route)

RB3*_*B34 3 python decorator flask

编辑2:我误解了装饰器是如何工作的.即使未调用装饰函数(即使您可能看不到它的效果),装饰器也会运行.function = dec(function)将是一个显示装饰器功能的等效方式,显然在这种情况下,dec()函数在没有调用function()的情况下运行.

编辑:为什么我的帖子被投票没有解释?我该如何解决?有多个答案,一个清楚地回答了这个问题.有什么问题?

我一直在学习python中的装饰器,我想我对它们有很好的把握.但是我仍然对app.route装饰器如何在烧瓶中工作感到有些困惑.根据我的理解,装饰器会更改函数的行为,但除非调用该函数,否则不会运行.所以,如果我有:

@app.route("/")
def hello():
    return "Hello world"

hello()
Run Code Online (Sandbox Code Playgroud)

hello函数将传递给app.route,并且装饰器指令将执行的任何行为.但是在烧瓶应用程序中,函数本身似乎永远不会运行(在上面的示例中它是).如果它的装饰函数从未被调用,那么route function/decorator是如何执行的?我知道app.route本质上将"/"及其相应的函数存储在字典中,但我不明白如何在没有调用装饰函数的情况下执行此代码.我假设它在某种程度上连接到了烧瓶应用程序结束时的app.run,但我不清楚app.run如何调用你定义的函数.

编辑:添加到我在这里显示的内容.这个解释有一个例子:https://ains.co/blog/things-which-arent-magic-flask-part-1.html那引发了同样的问题.我认为需要调用hello()才能使路由函数执行任何操作.

class NotFlask():
    def __init__(self):
        self.routes = {}

    def route(self, route_str):
        def decorator(f):
            self.routes[route_str] = f
            return f

        return decorator

    def serve(self, path):
        view_function = self.routes.get(path)
        if view_function:
            return view_function()
        else:
            raise ValueError('Route "{}"" has not been 
registered'.format(path))


app = NotFlask()

@app.route("/")
def hello():
    return "Hello World!"
Run Code Online (Sandbox Code Playgroud)

wkl*_*wkl 12

Python装饰器是这样的:

@decorator
def func():
    pass
Run Code Online (Sandbox Code Playgroud)

可以改为看起来像这样:

def func():
    pass

decorator(func)
Run Code Online (Sandbox Code Playgroud)

或者换句话说,它们是具有功能的功能.在某些情况下,您可能不会立即看到装饰器的效果,因此看起来装饰器本身在调用它所装饰的函数之前不会被使用,但这不是Python装饰器的实际限制.

在您的代码中,@app.route("/")是一个装饰器,它为app对象添加一个端点.它实际上并没有修改函数的任何行为,而是简化了过程.没有route()装饰器,这就是你在Flask中进行等效路线注册的方法.

from flask import Flask
app = Flask(_name_)

def hello():
    return "Hello world"

app.add_url_rule("/", "hello", hello)
Run Code Online (Sandbox Code Playgroud)

如果你看看Flask中装饰器实现route,你会发现这是等价的.

def route(self, rule, **options):
        """A decorator that is used to register a view function for a
        given URL rule.  This does the same thing as :meth:`add_url_rule`
        but is intended for decorator usage::
            @app.route('/')
            def index():
                return 'Hello World'
        For more information refer to :ref:`url-route-registrations`.
        :param rule: the URL rule as string
        :param endpoint: the endpoint for the registered URL rule.  Flask
                         itself assumes the name of the view function as
                         endpoint
        :param options: the options to be forwarded to the underlying
                        :class:`~werkzeug.routing.Rule` object.  A change
                        to Werkzeug is handling of method options.  methods
                        is a list of methods this rule should be limited
                        to (``GET``, ``POST`` etc.).  By default a rule
                        just listens for ``GET`` (and implicitly ``HEAD``).
                        Starting with Flask 0.6, ``OPTIONS`` is implicitly
                        added and handled by the standard request handling.
        """
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator
Run Code Online (Sandbox Code Playgroud)

因此,您可以看到route将其添加到应用程序的路由器,因此一旦Flask应用程序获得请求,它就会决定如何为已请求的端点执行代码/视图.