用metaclass来实现AOP
meta-programming是AOP实现的经常性手段,而这里要展示的,是利用Python的metaclass能力来实现 AOP。
当a的setx方法被调用时,会被“拦截”,先输出pre...然后是原始setx的方法调用,最后输出post...
class MetaAll(type):
def __new__(mcl, name, bases, dict):
def log(func):
def f(*args, **kwds):
print 'pre %s' % func.__name__
value = func(*args, **kwds)
print 'post %s' % func.__name__
return value
return f
for attr, value in dict.iteritems():
if attr.startswith('set'):
dict[attr] = log(value)
return super(MetaAll, mcl).__new__(mcl, name, bases, dict)
__metaclass__ = MetaAll
class A:
def __init__(self):
self.__x = 1
def getx(self):
return self.__x
def setx(self, value):
self.__x = value
a = A()
a.setx(2)
print a.getx()
def __new__(mcl, name, bases, dict):
def log(func):
def f(*args, **kwds):
print 'pre %s' % func.__name__
value = func(*args, **kwds)
print 'post %s' % func.__name__
return value
return f
for attr, value in dict.iteritems():
if attr.startswith('set'):
dict[attr] = log(value)
return super(MetaAll, mcl).__new__(mcl, name, bases, dict)
__metaclass__ = MetaAll
class A:
def __init__(self):
self.__x = 1
def getx(self):
return self.__x
def setx(self, value):
self.__x = value
a = A()
a.setx(2)
print a.getx()
看到那个__metaclass__变量了吗?如果你赋给它另外一个metaclass的话它会产生其他效应(我这里做的是 logging,其他的可能有例如timing、access control、transaction, etc.),这是魔法!^_^ 最魔力十足的地方是我甚至可以把一个metaclass传进模块中去,给__metaclass__动态的赋值(赋metaclass),这意味着我可以通过meta-programming动态的改变我程序的逻辑,或者不需要改动原有代码即可添加新功能(或修改)等特点!
整个演示就当作抛砖引玉吧,代码我就不细讲了,因为概念太复杂了,不是一两句能说得明白的。有兴趣的朋友可以研究一下Python。; -)