What is Python\'s equivalent of Ruby\'s method_missing
method? I tried using __getattr__
but this hook applies to fields too. I only want to interc
Although I don't recommend it!!!!!!!!!!!!!!!!!!!!!
this sort of comes closer to implementing the behavior of calling the special method for every name that does not correspond to a callable attribute/method. Of course they still don't really have separate namespaces so it may feel a bit weird. It works by overriding __getattribute__
which works at a lower level then __getattr__
it tries to fetch an attribute if it fails it returns a curried special method to call with the name you called it with, if it succeeds it passes it on if its callable otherwise it
wraps the result with a proxy object which acts in almost exactly the same way afterwards except it implements call with your special method.
It doesn't allow you to access the calling object because I couldn't think of a good way to do that without sort of leaking memory(the calling object) if it's already a non-callable attribute which you store(the only think I can think of is to start a new thread that deletes it after a minute, by then you have presumably called it unless you are using it in a closure which wouldn't be supported in that case).
Edit: I forgot callable may have some false positives.
depends on the http://pypi.python.org/pypi/ProxyTypes library
from peak.util.proxies import ObjectWrapper
from functools import partial
def m(name, *args, **kwargs):
print(name,repr(args),repr(kwargs))
class CallProxy(ObjectWrapper):
def __init__(self, obj, m, method_name):
ObjectWrapper.__init__(self, obj)
object.__setattr__(self, "_method_name", method_name)
object.__setattr__(self, "_m", m)
def __call__(self, *args, **kwargs):
return self._m(self._method_name, *args,**kwargs)
class Y(object):
def __init__(self):
self.x = [3]
def __getattribute__(self, name):
try:
val = object.__getattribute__(self, name)
if not callable(val):
return CallProxy(val, m, name)
else:
return val
except AttributeError:
return partial(m, name)
In [2]: y=Y()
In [3]: y.x
Out[3]: [3]
In [4]: y.z
Out[4]:
In [5]: y.zz([12])
('zz', '([12],)', '{}')
In [6]: y.x.append(5)
In [7]: y.x
Out[7]: [3, 5]
In [8]: y.x(1,2,3,key="no")
('x', '(2, 3)', "{'key': 'no'}")