python flask route中装饰器的使用

问题: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中形成映射关系。

上一篇:cal命令详解


下一篇:通过Long类型的出生日期算年龄