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

标签 python flask decorator

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

编辑:为什么我的帖子在没有解释的情况下被否决?我该如何解决?有多种答案,其中一个清楚地回答了问题。问题是什么?

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

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

hello()

hello 函数将被传递给 app.route 并且装饰器指示的任何行为都将执行。然而,在flask应用程序中,函数本身似乎从未运行过(在我上面的例子中是这样)。如果路由函数/装饰器从未调用过它所装饰的函数,它是如何执行的?我知道 app.route 本质上将“/”及其相应的函数存储在字典中,但我不明白在没有任何装饰函数调用的情况下如何执行此代码。我假设它以某种方式连接到 flask 应用程序末尾的 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!"

最佳答案

像这样的 Python 装饰器:

@decorator
def func():
    pass

可以改为如下所示:
def func():
    pass

decorator(func)

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

在您的代码中,@app.route("/")是一个装饰器,它将端点添加到 app目的。它实际上并没有修改函数的任何行为,而是简化过程的糖。没有 route()装饰器,这就是您在 Flask 中进行等效路由注册的方式。
from flask import Flask
app = Flask(_name_)

def hello():
    return "Hello world"

app.add_url_rule("/", "hello", hello)

如果你看看 implementation of the route decorator在 Flask 中,你会看到这是等价的。
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

所以你可以看到 route将它添加到应用程序的路由器,因此一旦 Flask 应用程序收到请求,它就会决定如何为所请求的端点执行代码/ View 。

关于python - 装饰函数如何在 flask /python 中工作? (app.route),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46123448/

相关文章:

python - 在 PyQT 中获取 QLabel 点击的信息

python - 对 im2txt 微调 inception v3 时损失并没有减少

python - Flask Caching 文件系统缓存是否跨进程共享?

python - GET 数据作为函数参数与来自 requests.arg 的项目之间的区别

Python heroku 为socket.io 聊天应用程序配置procfile Gunicorn + gevent |运行时错误: You need to use the gevent-websocket server

javascript - 在 React 中使用方法装饰器时绑定(bind) this

python - 当 @mock.patch 装饰器在 Python 中的装饰方法/函数的参数数量多时,它会做什么?

python - WxPython 使用列表框和其他带有按钮的用户输入

python - 发送消息时禁用登录 Flask-Mail

python - 为什么装饰器必须在调用之前声明,而函数却不需要?