问题:route中的装饰器为什么感觉和平时使用的不太一样,装饰器带参数和不太参数有什么区别?被修饰的函数带参数和不带参数有什么区别?
测试1:装饰器不带参数,被修饰的函数也不带参数。
def log(func): print"execute log" print func def use_log(): print "execute use log" def wrapper(): print "start" func() print "end" return return wrapper return use_log @log def cal(): print "1+2"
此时输出为:
execute log <function cal at 0x7fa64535f668> #这里的function为cal的函数地址
如果执行cal()那么将会使用use_log函数,返回的是wrapper()
execute log <function cal at 0x7f42ee7a4668> execute use log
如果执行cal()的返回值,那么将执行cal()函数体的内容
result = cal() result()
结果为:
execute log <function cal at 0x7f38dc4d1668> execute use log start 1+2 end
测试2:如果装饰器带参数,被修饰的函数不带参数
def log(func): #这里的func为装饰器函数参数 print"execute log" print func #这里的func为装饰器函数参数 def use_log(func): #这里的func为函数cal()的地址 print "execute use log" print func #这里的func为函数cal()的地址 def wrapper(): print "start" func() print "end" return return wrapper return use_log @log('log') def cal(): print "1+2" #这个时候数输出结果为: execute log log execute use log <function cal at 0x7f0c666b46e0>
这个时候调用cal()那么将会执行wrapper()的函数体+cal()的函数体。
测试3:如果装饰器不带参数,被修饰的函数带参数
def log(func): #func 为cal()函数的地址 print"execute log" def use_log(param): #param为cal的参数param print "execute use log" print param def wrapper(): print "start" func(param) #func 为cal()函数的地址,param为cal的参数param print "end" return return wrapper return use_log @log def cal(param): print "1+2" result = cal('cal') result() #执行的结果为: execute log execute use log cal start 1+2 end #如果注掉最后两行代码,那么只有输出 execute log
测试4:如果装饰器带参数,被修饰的函数也带参数。最复杂的情况。
def log(func): #func为装饰器的参数 print"execute log" def use_log(func): #func为cal的函数地址 print "execute use log" print func #func为cal的函数地址 def wrapper(param): #param为cal的参数 print "start" func(param) print "end" return return wrapper return use_log @log('test') def cal(param): print "1+2" result = cal('cal') #执行的结果为: execute log execute use log <function cal at 0x7f23bbc6d6e0> start 1+2 end
经过上面的分析之后,再看flask中使用的是哪种情况:
样例代码:
from flask import Flask app = Flask(__name__) @app.route('/') def hello(): print 'execute hello function' return 'Hello, World!'
@app.route('/')的代码如下:
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) print "this param has been accessed" return f return decorator
可以看到装饰器的参数为‘/’,被修饰的函数为:hello(),所以这里属于第二种情况,即使不调用hello()函数,decorator的函数体也是被执行的,也就是说,只要使用装饰器添加了路由规则,那么就会被加入到map中形成映射关系。