欢迎各位兄弟 发布技术文章
这里的技术是共享的
好了,现在我们来看一下各种decorator的例子:
这个例实在是太经典了,整个网上都用这个例子做decorator的经典范例,因为太经典了,所以,我这篇文章也不能免俗。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from functools import wrapsdef memo(fn): cache = {} miss = object() @wraps(fn) def wrapper(*args): result = cache.get(args, miss) if result is miss: result = fn(*args) cache[args] = result return result return wrapper@memodef fib(n): if n < 2: return n return fib(n - 1) + fib(n - 2) |
上 面这个例子中,是一个斐波拉契数例的递归算法。我们知道,这个递归是相当没有效率的,因为会重复调用。比如:我们要计算fib(5),于是其分解成 fib(4) + fib(3),而fib(4)分解成fib(3)+fib(2),fib(3)又分解成fib(2)+fib(1)…… 你可看到,基本上来说,fib(3), fib(2), fib(1)在整个递归过程中被调用了两次。
而我们用decorator,在调用函数前查询一下缓存,如果没有才调用了,有了就从缓存中返回值。一下子,这个递归从二叉树式的递归成了线性的递归。
这个例子没什么高深的,就是实用一些。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | import cProfile, pstats, StringIOdef profiler(func): def wrapper(*args, **kwargs): datafn = func.__name__ + ".profile" # Name the data file prof = cProfile.Profile() retval = prof.runcall(func, *args, **kwargs) #prof.dump_stats(datafn) s = StringIO.StringIO() sortby = 'cumulative' ps = pstats.Stats(prof, stream=s).sort_stats(sortby) ps.print_stats() print s.getvalue() return retval return wrapper |
下面这个示例展示了通过URL的路由来调用相关注册的函数示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 | class MyApp(): def __init__(self): self.func_map = {} def register(self, name): def func_wrapper(func): self.func_map[name] = func return func return func_wrapper def call_method(self, name=None): func = self.func_map.get(name, None) if func is None: raise Exception("No function registered against - " + str(name)) return func()app = MyApp()@app.register('/')def main_page_func(): return "This is the main page."@app.register('/next_page')def next_page_func(): return "This is the next page."print app.call_method('/')print app.call_method('/next_page') |
注意:
1)上面这个示例中,用类的实例来做decorator。
2)decorator类中没有__call__(),但是wrapper返回了原函数。所以,原函数没有发生任何变化。