>>> import bondage
>>>
>>> class C(object):
... @bondage.discipline(int)
... def foo(self, arg):
... print 'int'
... @foo.discipline(str)
... def foo(self, arg):
... print 'str'
... @foo.discipline(int, str, int)
... def foo(self, arg1, arg2, arg3):
... print 'int, str, int'
...
>>> c = C()
>>> c.foo(1)
int
>>> c.foo('a')
str
>>> c.foo(1, 'a', 1)
int, str, int
>>> c.foo([])
Traceback (most recent call last):
File "", line 1, in <module>
File "bondage.py", line 18, in <lambda>
return lambda *args: self._dispatch(obj, *args)
File "bondage.py", line 22, in _dispatch
return self._argspecs[argspec](obj, *args)
KeyError: (<type 'list'>,)
>>>
I'd like to make it clear that there is absolutely no excuse for perpetrating this sort of insanity, ever. With that said, here's how I did it:
class discipline(object):
def __init__(self, *argspec):
self._argspecs = {}
self.discipline(*argspec)
def discipline(self, *argspec):
self._argspec = argspec
return self
def __call__(self, f):
self._argspecs[self._argspec] = f
return self
def __get__(self, obj, objtype=None):
return lambda *args: self._dispatch(obj, *args)
def _dispatch(self, obj, *args):
argspec = tuple(map(type, args))
return self._argspecs[argspec](obj, *args)
Obviously it's a stupid implementation, and if you wanted to do this properly you'd have to pay attention to subtypes, and do something clever with numeric types, and... oh, God, what am I saying?
Enough!
If you really want to do this "properly", use some other language where it's already built in, and begone.