Python的AOP利器:装饰器

AOP(面向切面)算是一个比较热门的话题,以至于有一种论调说“AOP会替代OOP”,然而事实上AOP跟OOP的关注点并不相同。面向对象(OOP)的目的在于抽象 ,而面向切面(AOP)的目的在于解耦

在Java中面向切面编程需要使用反射(动态代理)实现,操作比较麻烦。而在Python语言中则提供了一个很好用的语法糖--装饰器.

首先,声明一个简单的函数:

  def foo():
      print("function foo")

这个函数很简单,仅仅输出一句话.如果现在要给这个函数添加执行时间的功能,在不使用装饰器的情况下可能会这么写:

from datetime import datetime  
def foo():  
    begin=datetime.now().microsecond
    print("function foo")
    end=datetime.now().microsecond
    print("函数foo耗时%d"%end-begin)

使用这种方法使得方法体中多了很多跟核心业务无关的代码,毫无疑问在后期扩展和维护过程中增加难度.在Java程序中可以使用动态代理的方法解决,而在Python程序中有更好或者说更容易实现的方法.下面定义一个专门处理程序耗时的方法,接收一个函数对象,返回一个函数对象:

from datetime import datetime  
def timer(func):  
    def _timer(*args,**kw):
        begin=datetime.now().microsecond
        rs=func(*args,**kw)
        end=datetime.now().microsecond
        print("函数%s耗时%d"%(func.__name__,end=begin))
        return rs
    return _timer

修改foo函数:

@timer
def foo():  
      print("function foo")

这种写法跟Java的注解很像.执行foo函数,可以看到只添加了一行代码就为函数添加了新功能.从代码上看,其效果类似于timer(foo)().

如果装饰器函数本身需要接收参数,只需稍作修改,如下:

from datetime import datetime  
def timer(arg):  
    print(arg)
    def decorator(func):
        def _timer(*args,**kw):
            begin=datetime.now().microsecond
            rs=func(*args,**kw)
            end=datetime.now().microsecond
            print("函数%s耗时%d"%(func.__name__,end=begin))
            return rs
        return _timer
    return decorator

同时在为foo函数添加装饰器时写作@timer(arg)形势即可,其执行效果类似timer(arg)(foo)().

author:@Memory_Leak