¿Cómo funcionan las funciones decoradas en matraz / python? (app.ruta)

Edición 2: entendí mal cómo trabajan los decoradores. El decorador se ejecuta incluso si no se llama a la función decorada (aunque es posible que no vea sus efectos). function = dec (function) sería una forma equivalente de mostrar lo que hace un decorador y, obviamente, en ese escenario, la función dec () se ejecuta sin ninguna llamada a function ().

Edit: ¿Por qué mi publicación está siendo rechazada sin explicación? ¿Cómo puedo arreglarlo? Hay múltiples respuestas, una que responde claramente a la pregunta. ¿Cual es el problema?

He estado aprendiendo sobre decoradores en python y creo que los conozco bien. Sin embargo, todavía estoy un poco confundido acerca de cómo funciona el decorador de app.ruta en el matraz. Según tengo entendido, el decorador cambia el comportamiento de una función pero no se ejecuta a menos que se llame a la función. Así que si tengo:

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

La función de saludo se pasará a app.ruta y se ejecutará cualquier comportamiento que dicte el decorador. Sin embargo, en las aplicaciones de matraz, la función en sí nunca parece ejecutarse (en mi ejemplo anterior es). ¿Cómo se ejecuta la función de ruta / decorador si la función que decora nunca se llama? Sé que app.ruta esencialmente almacena la “/” junto con su función correspondiente en un diccionario, pero no entiendo cómo se ejecuta este código sin ninguna llamada de la función decorada. Supongo que de alguna manera está conectado a app.run al final de las aplicaciones del matraz, pero no estoy claro cómo app.run puede llamar a las funciones que definió.

Editar: para agregar a lo que he mostrado aquí. Hay un ejemplo de esta explicación: https://ains.co/blog/things-which-arent-magic-flask-part-1.html Eso plantea las mismas preguntas. Creo que se debe llamar a hello () para que la función de ruta haga algo.

 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!" 

A los decoradores de Python les gusta esto:

 @decorator def func(): pass 

Se puede cambiar para que se vea así en su lugar:

 def func(): pass decorator(func) 

O, en otras palabras, son funciones que toman funciones. En algunas circunstancias, es posible que no veas los efectos del decorador de inmediato, por lo que puede parecer que el decorador no se usa hasta que se llama a la función que decora, pero eso no es una restricción real de los decoradores de Python.

En su código, @app.route("/") es un decorador que agrega un punto final al objeto de la app . En realidad, no modifica ningún comportamiento de la función, sino que es azúcar para simplificar el proceso. Sin el decorador route() , esta es la forma de hacer el registro de ruta equivalente en Flask.

 from flask import Flask app = Flask(_name_) def hello(): return "Hello world" app.add_url_rule("/", "hello", hello) 

Y si nos fijamos en la implementación del decorador de route en Flask, verás que este es el equivalente.

 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 

Así que puede ver que la route agrega al enrutador de la aplicación, por lo que una vez que la aplicación Flask recibe una solicitud, decide cómo ejecutar el código / vista para el punto final que se ha solicitado.

El fragmento de código está llamando directamente a la función de hello . Es por eso que la función se está ejecutando.

Para Flask, usted define las rutas usando las funciones de decorador. Cuando navega a una URL que coincide con el decorador, ejecutará la función decorada. En este ejemplo, si navego a “/” en mi servidor web, la función de hello se ejecutará.

Para ejecutar su servidor, debe hacer lo siguiente desde la línea de comando (que también se puede encontrar en la documentación de Flask) .

 $ export FLASK_APP=hello.py $ flask run 

Donde hello.py es el nombre del archivo que contiene su código de Python. También debe eliminar la llamada directa a hello() en su archivo. Luego abra un navegador y navegue a http: // localhost: 5000 / para ver el resultado.

¿Cómo funcionan los decoradores?

Los decoradores son funciones que envuelven otras funciones en un bash de alterar el comportamiento de la subfunción. Puedes leer la explicación muy detallada en la wiki de Python .

Los decoradores asumen una función como su argumento. Normalmente, los decoradores ejecutan algunos códigos antes de ejecutar la subfunción. Por ejemplo, si desea agregar autenticación a ciertos puntos finales de su aplicación Flask, puede usar decoradores. Los decoradores verifican que un usuario esté autenticado para usar un recurso antes de que se ejecute el código real de ese recurso.

 @authenticate def hello(): return "Hello world" 

La función de authenticate se ejecutará primero. Y luego, si el usuario está autenticado, llamará a hello para ejecutar el rest; de lo contrario, enviará un error al usuario. En el caso de los decoradores de Flask, están verificando si una solicitud entrante coincide con la ruta que ha especificado. Si lo hace, entonces ejecuta la función. De lo contrario, comprueba la siguiente ruta.

El siguiente artículo es para ir a aprender sobre decoradores: https://realpython.com/blog/python/primer-on-python-decorators/