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