最近在看FP相关, 看到Closure, 想起这个... python的装饰器方法是用闭包实现的
Closure是什么就不解释了, 可以看上面第一个blog
装饰器, 经典的设计模式, 动态地给一个对象添加一些额外的职责.
大家在写代码的时候, 除了核心的逻辑, 往往还有许多辅助的逻辑, 比如, log, try catch, lock, time计时, 等等...
如果都混在一起, 严重影响代码的整洁度, 比如log或try catch这种需要随处加的, 非常影响开发效率, 和可读性
而装饰器最大的应用, 就是将核心代码和辅助代码分离.
以time为例,大家在测performance的时候会在自己代码里面加上大量的这样的代码, 非常烦...
import time def foo(): start = time.clock() print 'in foo()' end = time.clock() print 'used:', end - start
Python这种动态语言, function也是first-class, 所以简单改进如下, 虽然简单, 但是这已经属于装饰器设计模式
这种改动的问题在于, 你想想这种performance代码都是临时加上的, 如果每次都需要修改函数名来测时间, 相当麻烦
import time def foo(): print 'in foo()' def timeit(func): start = time.clock() func() end =time.clock() print 'used:', end - start
import time def foo(): print 'in foo()' def timeit(func): def wrapper(): start = time.clock() func() end =time.clock() print 'used:', end - start return wrapper foo = timeit(foo) foo()
装饰器方法的Python语法糖,@
@timeit,在定义上加上这一行与另外写foo = timeit(foo)完全等价
import time def timeit(func): def wrapper(): start = time.clock() func() end =time.clock() print 'used:', end - start return wrapper @timeit def foo(): print 'in foo()'
python中内嵌的装饰器方法, 分别是staticmethod、classmethod和property
再给出一个lock的例子, 对于线程lock需要传入同一个lock对象, 更加体现出闭包
博主嫌这个方法不够优雅, 写了套更简单的
把lock对象的生成封装到一个Decorate类中, 并在类初始化是完成对于所有类函数自动的wrapper, 这个取决于python的动态特性, 可以run-time时获取, 修改函数的逻辑.
具体可以参考第一个blog
def sync(func): def wrapper(*args, **kv): self = args[0] self.lock.acquire() try: return func(*args, **kv) finally: self.lock.release() return wrapper class Foo(object): def __init__(self, …): self.lock = threading.Lock() @sync def interface1(self, …): do something @sync def interface2(self, …): do something
本文章摘自博客园,原文发布日期:2013-02-08