Вот вариант предложения Unknown, который возвращает вызываемый экземпляр «обертки» вместо запрошенной функции. Это не требует украшения каких-либо методов:
class F(object):
def __init__(self, func):
self.func = func
return
def __call__(self, *args, **kw):
print "Calling %r:" % self.func
print " args: %r" % (args,)
print " kw: %r" % kw
return self.func(*args,**kw)
class C(object):
def __init__(self):
self.a = 'an attribute that is not callable.'
return
def __getattribute__(self,name):
attr = object.__getattribute__(self,name)
if callable(attr):
# Return a callable object that can examine, and even
# modify the arguments prior to calling the method.
return F(attr)
# Return the reference to any non-callable attribute.
return attr
def m(self, *a, **kw):
print "hello from m!"
return
>>> c=C()
>>> c.a
'an attribute that is not callable.'
>>> c.m
<__main__.F object at 0x63ff30>
>>> c.m(1,2,y=25,z=26)
Calling <bound method C.m of <__main__.C object at 0x63fe90>>:
args: (1, 2)
kw: {'y': 25, 'z': 26}
hello from m!
>>>
Муравьи Аасма выше делает важный момент относительно рекурсии при использовании __getattribute__
. Он вызывается всеми поисками атрибутов в self
, даже внутри метода __getattribute__
. Несколько других примеров включают ссылки на self.__dict__
внутри __getattribute__
, которые будут повторяться до тех пор, пока вы не превысите максимальную глубину стека! Чтобы избежать этого, используйте один из
версии базового класса __getattribute__
(например, object.__getattribute__(self,name)
.)