今天我们不讲三国,我们好好讲一讲python的decorator(装饰器)
刚开始接触这个概念其实很容易迷惑,我也是从半懂不懂就开始使用,因为flask的例子中总会提到这个route装饰器
@app.route('/')
def index():
return render_template('index.html')
那么,到底什么是decorator呢? 其实decorator就是一个函数,这个函数接受另外一个函数作为参数,@decorate这种写法这是python提供的语法糖,看下面的例子
@decorate
def target():
print('running target')
这段代码的意思跟下面这段完全一样
def target():
print('running target')
target = decorate(target)
但是请记住,这两段代码最后结果中的target已经不是原来的target函数的引用了,而是decorate(target)的引用。可能比较拗口,但是一定要理解。
这里有一个问题,非常重要,就是python什么时候执行decorators
来,下面我们通过代码片段abc.py来看
registry = []
def register(func):
print('running register(%s)' % func)
registry.append(func)
return func
@register
def f1():
print('running f1')
@register
def f2():
print('running f2')
def main():
print('running main')
print('registry ->', resigtry)
f1()
f2()
if __name__ == '__main__'
main()
保存以上代码,并运行。
python3 abc.py
你可以看到结果是
running register f1
running register f2
running main
registry -> [f1,f2]
running f1
running f2
你可能已经猜到这里面的关键了。
在模块被载入的时候,装饰器就已经执行了。but! 注意这里的but! 被装饰的函数,比如f1,f2是要等到显式的调用才会执行。这里是装饰器的关键。
写到这里,是不是可以大概知道flask中装饰器是怎么起作用的?
@app.route('/')
def index():
return render_template('index.html')
我们来看一下flask中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
我们来分析一下这个函数。
因为app.route需要接受参数,路由规则是必须的。所以
def route(self, rule, **option)
其实是一个函数工厂,真正的decorator从内部的decorator()函数开始
decorator(f)函数内部有一个函数 add_url_rule
这段代码
@app.route('/')
def index():
pass
和下面这段代码表达的意思是一样的。
def index():
pass
app.add_url_rule('/', 'index', index)
也就是decorator(f)内部做的事情,在函数内部调用add_url_rule()
装饰器真的是一个很方便的功能。
End