欢迎各位兄弟 发布技术文章
这里的技术是共享的
好了,现在我们来看一下各种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 wraps def 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 @memo def 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, StringIO def 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返回了原函数。所以,原函数没有发生任何变化。