本文代码借用 廖雪峰的python教程(官网:http://www.liaoxuefeng.com/)
不了解装饰器的可以先看教程
直接上带参数装饰器的代码
def log(text): def decorator(func): def wrapper(*args, **kw): print '%s %s():' % (text, func.__name__) return func(*args, **kw) return wrapper return decorator @log('execute') def now(): print '2013-12-25' now() 控制台输出: execute now(): 2013-12-25
这都很好理解,但是我在看到教程中的用flask框架写WEB应用时
@app.route('/', methods=['GET', 'POST']) def home(): return '<h1>Home</h1>'
只要在函数前面添加这样的装饰器,就能达到自动地把URL和函数给关联起来的目的
可是为什么这样写装饰器就能有这样的效果呢
我们来看了一下这个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
体现这个功能的肯定是在return f前面的两行代码,它把这个映射规则添加带app对象中,细节我们不用理会
可是,这些映射规则不是应该在我们调用home函数前就应该建立起来吗?不然怎么自动映射到home这个函数。
会造成这样的困惑的原因是我一直误解的装饰器的装饰过程,其实装饰器的装饰过程是在函数定义的时候就执行了,即你在调用home之前,home早就装饰器碉堡换成装饰器返回的函数了。也就是说,就算你没调用home函数,装饰器的代码也早就执行了。
我们用代码来验证一下:
def log(text): print 'print 1' def decorator(func): print 'print 2' def wrapper(*args, **kw): print '%s %s():' % (text, func.__name__) return func(*args, **kw) return wrapper return decorator @log('NiHao') def now(): print '2013-12-25' 控制台输出: print 1 print 2
结果显示:我们还没调用now(),两个print语句已经执行了。
得证。