Mar*_*son 8 python metaprogramming
我正在将类A(我从其他人导入,因此我无法修改它)实例化到我的类X.
有没有办法可以拦截或包装对A中方法的调用?即,在下面的代码中我可以打电话
x.a.p1()
Run Code Online (Sandbox Code Playgroud)
并获得输出
X.pre
A.p1
X.post
Run Code Online (Sandbox Code Playgroud)
很多TIA!
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()
Run Code Online (Sandbox Code Playgroud)
以下是我和我的同事提出的解决方案:
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()
Run Code Online (Sandbox Code Playgroud)
得到:
pre
stuff
post
pre
post
0
Run Code Online (Sandbox Code Playgroud)
因此,在创建对象的实例时,请使用PrePostCaller对象进行包装.之后,继续使用该对象,就好像它是包装对象的实例一样.使用此解决方案,您可以基于每个实例进行包装.