Python:使用前后方法包裹方法调用
我正在我的类 X 中创建一个类 A 的实例(这个类 A 是从别人那里导入的,所以我不能修改它)。
有没有办法可以拦截或包装对 A 中方法的调用?
也就是说,在下面的代码中,我能否调用
x.a.p1()
并得到输出
X.pre
A.p1
X.post
非常感谢!
class A:
# in my real application, this is an imported class
# that I cannot modify
def p1(self): print 'A.p1'
class X:
def __init__(self):
self.a=A()
def pre(self): print 'X.pre'
def post(self): print 'X.post'
x=X()
x.a.p1()
6 个回答
1
一个简单直接的解决办法就是为A类写一个包装类,专门用来做这个事情。
3
你可以直接修改A这个实例,把p1这个函数换成一个包装函数:
def wrapped(pre, post, f):
def wrapper(*args, **kwargs):
pre()
retval = f(*args, **kwargs)
post()
return retval
return wrapper
class Y:
def __init__(self):
self.a=A()
self.a.p1 = wrapped(self.pre, self.post, self.a.p1)
def pre(self): print 'X.pre'
def post(self): print 'X.post'
8
这是我和我的同事们想出的解决办法:
from types import MethodType
class PrePostCaller:
def __init__(self, other):
self.other = other
def pre(self): print 'pre'
def post(self): print 'post'
def __getattr__(self, name):
if hasattr(self.other, name):
func = getattr(self.other, name)
return lambda *args, **kwargs: self._wrap(func, args, kwargs)
raise AttributeError(name)
def _wrap(self, func, args, kwargs):
self.pre()
if type(func) == MethodType:
result = func( *args, **kwargs)
else:
result = func(self.other, *args, **kwargs)
self.post()
return result
#Examples of use
class Foo:
def stuff(self):
print 'stuff'
a = PrePostCaller(Foo())
a.stuff()
a = PrePostCaller([1,2,3])
print a.count()
结果是:
pre
stuff
post
pre
post
0
所以在创建你对象的实例时,要把它放在一个叫做 PrePostCaller 的对象里。之后,你可以像使用普通对象一样继续使用这个被包装的对象。这个方法让你可以针对每个实例单独进行包装。