Here’s an example of how to use metaclass programming to intercept class method calls similar to the method_missing technique in Ruby:
class ClassMethodInterceptor(type):
def __getattr__(cls, name):
return lambda *args, **kwargs: \
cls.static_method_missing(name, *args, **kwargs)
def static_method_missing(cls, method_name, *args, **kwargs):
e = "type object 'static.%s' has no attribute '%s'" \
% (cls.__name__, method_name)
raise AttributeError(e)
class Example(object):
__metaclass__ = ClassMethodInterceptor
def __getattr__(self, name):
return lambda *args, **kwargs: \
self.method_missing(name, *args, **kwargs)
def method_missing(self, method_name, *args, **kwargs):
e = "type object '%s' has no attribute '%s'" \
% (self.__class__.__name__, method_name)
raise AttributeError(e)
@classmethod
def static(cls):
print 'static.%s' % cls.__name__
def instance(self):
print self.__class__.__name__
>>> Example.static()
static.Example
>>> Example.foo()
Traceback (most recent call last):
...
File "example.py", line 12, in static_method_missing
raise AttributeError(e)
AttributeError: type object 'static.Example' has no attribute 'foo'
>>> e = Example()
>>> e.instance()
Example
>>> e.foo()
Traceback (most recent call last):
...
File "example.py", line 26, in method_missing
raise AttributeError(e)
AttributeError: type object 'Example' has no attribute 'foo'
If you ever implement something like this, remember that Python doesn’t distinguish between methods and attributes the way Ruby does. There is no difference in Python between properties and methods. A method is just a property whose type is instancemethod.