python装饰器

def dec(f):  # 不带参数的装饰器 里面包一层就可以  这里的 参数 都是固定的,没有可以给装饰器传参数的地方
    def inner(*args, **kwargs):
        print('dec')
        return f(*args, **kwargs)

    return inner


def dec_2(t):  # 带参数的装饰器 里面包两层  t为装饰器参数
    print('t=', t)   # @后直接执行

    def inner(f):  # f为传进来的函数,不能变
        print('f=', f)  # @后直接执行

        def inner_2(*args, **kwargs):  # 这里的参数为为被装饰函数本身的参数
            print(t)  # 调用原函数的时候才执行
            return f(*args, **kwargs)

        return inner_2

    return inner


@dec  # 装饰器相当于执行  fun1= dec(fun1)
def fun1(str_):
    print(str_)
    print('aa')


@dec_2('1')  # 带参数装饰器 @ 相当于执行 fun2 = dec_2('1')(fun2)  和不带参数不一样
def fun2(str_):
    print(str_)
    print('aa')


if __name__ == '__main__':
    fun1('args')
    print()
    fun2('args')

flask中app.route 是装饰器实现的,查看源码

@app.route('/index', methods=['POST', 'GET'], endpoint='bb')
def aa():
    return '234'
app.run()

app.route装饰器

    def route(self, rule, **options):
        def decorator(f):
            endpoint = options.pop('endpoint', None)
            self.add_url_rule(rule, endpoint, f, **options)
            return f
        return decorator

 

flask例子:

这里app.route给参数了 所以相当于代码  为aa=app.route('/index', mehtods=['POST', 'GET'], endpoint='bb')(aa)

本来装饰器中应该有3个函数,2函数是直接执行的,最内层的是调用函数执行的, flask这样写的话,就没有调用aa本身时执行的了,而是直接运行了decorator函数

 

 

在self.add_url_rule源码

# app.py
@setupmethod
    def add_url_rule(self, rule, endpoint=None, view_func=None,
                     provide_automatic_options=None, **options):
        if endpoint is None:
            endpoint = _endpoint_from_view_func(view_func)
        options['endpoint'] = endpoint
        methods = options.pop('methods', None)

        # if the methods are not given and the view_func object knows its
        # methods we can use that instead.  If neither exists, we go with
        # a tuple of only ``GET`` as default.
        if methods is None:
            methods = getattr(view_func, 'methods', None) or ('GET',)
        if isinstance(methods, string_types):
            raise TypeError('Allowed methods have to be iterables of strings, '
                            'for example: @app.route(..., methods=["POST"])')
        methods = set(item.upper() for item in methods)

        # Methods that should always be added
        required_methods = set(getattr(view_func, 'required_methods', ()))

        # starting with Flask 0.8 the view_func object can disable and
        # force-enable the automatic options handling.
        if provide_automatic_options is None:
            provide_automatic_options = getattr(view_func,
                'provide_automatic_options', None)

        if provide_automatic_options is None:
            if 'OPTIONS' not in methods:
                provide_automatic_options = True
                required_methods.add('OPTIONS')
            else:
                provide_automatic_options = False

        # Add the required methods now.
        methods |= required_methods

        rule = self.url_rule_class(rule, methods=methods, **options)
        rule.provide_automatic_options = provide_automatic_options

        self.url_map.add(rule)
        if view_func is not None:
            old_func = self.view_functions.get(endpoint)
            if old_func is not None and old_func != view_func:
                raise AssertionError('View function mapping is overwriting an '
                                     'existing endpoint function: %s' % endpoint)
            self.view_functions[endpoint] = view_func

其实这里最重要的就是 建立了endpoint和 函数的对应关系 ,就是最后一句 self.view_functions[endpoint] = view_func

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值