学习flask源码之@app.route(“/”)

首先,我们一步步深入到@app.route的源码之中。

#scaffold.py
def setupmethod(f: F) -> F:
    f_name = f.__name__

    def wrapper_func(self, *args: t.Any, **kwargs: t.Any) -> t.Any:
        self._check_setup_finished(f_name)
        return f(self, *args, **kwargs)

    return t.cast(F, update_wrapper(wrapper_func, f))
class Scaffold:

    def _check_setup_finished(self, f_name: str) -> None:
        raise NotImplementedError

   @setupmethod
    def route(
        self, rule: str, **options: t.Any
    ) -> t.Callable[[ft.RouteDecorator], ft.RouteDecorator]:

        def decorator(f: ft.RouteDecorator) -> ft.RouteDecorator:
            endpoint = options.pop("endpoint", None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f

        return decorator

class Flask(Scaffold):
    def _check_setup_finished(self, f_name: str) -> None:
        if self._got_first_request:
            raise AssertionError(
                f"The setup method '{f_name}' can no longer be called"
                " on the application. It has already handled its first"
                " request, any changes will not be applied"
                " consistently.\n"
                "Make sure all imports, decorators, functions, etc."
                " needed to set up the application are done before"
                " running it."
            )

其中,setupmethod使用了functools的update_wrapper()。

functools module用于处理高阶函数(high-order function).

functools.update_wrapper()用于保留被装饰函数的信息,比如__name__,__doc__等。他的作用和@functools.wraps(func)是相同的。
来看一个例子对比使用前和使用后的区别。

def welcome(func):
    def wrapper_welcome(*args, **kwargs):
        'wrapper_welcome function'
        print("Welcome")
        return func(*args, **kwargs)
    return wrapper_welcome

@welcome
def greet(name):
    'greet function'
    print(f"hello {name}")
greet.__name__=wrapper_welcome
greet.__doc__ = wrapper_welcome function
#=========================================
def welcome(func):
    def wrapper_welcome(*args, **kwargs):
        'wrapper_welcome function'
        print("Welcome")
        return func(*args, **kwargs)
    functools.update_wrapper(wrapper_welcome,func)
    return wrapper_welcome

@welcome
def greet(name):
    'greet function'
    print(f"hello {name}")
greet.__name__=greet
greet.__doc__ = greet function

官方解释

typing.cast(typ, val)
Cast a value to a type.

This returns the value unchanged. To the type checker this signals that the return value has the designated type, but at runtime we intentionally don’t check anything (we want this to be as fast as possible).

由于python不会在运行时进行类型检查,python中的type checker指的是第三方提供的库,如mypy等,可参考这篇文章
typing.cast会告诉type checker,将val当做给定的type来对待。当typing.cast与mypy配合使用,就会发现可能存在的类型错误。所以,当没有mypy这样的库时,typing.cast是没有意义的。

未完待续…

Original: https://www.cnblogs.com/pitaya01/p/16375061.html
Author: somelovelanguage
Title: 学习flask源码之@app.route(“/”)

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/603974/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球