Вот решение, которое я и мои коллеги придумали:
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. После этого вы продолжаете использовать объект, как если бы он был экземпляром обернутого объекта. С помощью этого решения вы можете выполнять упаковку для каждого экземпляра.