There are two ways to do this:
- Delegation. Already in Python. Most Pythonic. Doesn't work for builtin types. Not exactly what you're looking for.
- Single Dispatch. Still a PEP. Works for builtin types. Precisely what you're looking for.
Delegation
You usually delegate responsibility to the object you're acting on, and you don't implement the logic in your function.
Here's an example: len
. The implementation of len
is very staightforward:
def len(obj):
return obj.__len__()
Different types (str
, list
, tuple
...) have different implementations, but they all work with the same function.
Now, if I want to define my own type, that works with len
, I can do:
class MyTypeOfLength3(object):
def __len__(self):
return 3
o = MyTypeOfLength3()
print len(o)
# 3
In your case, you would be implementing something that looks like len
.
(Note: this isn't the actual code for len
, but it's more or less equivalent.)
Single Dispatch
Of course, in some cases, that might not be practical. If that's your case, then the "Single Dispatch" PEP 443 is probably what you're looking for.
It suggests a new decorator that would accomplish what you're looking for:
>>> from functools import singledispatch
>>> @singledispatch
... def fun(arg, verbose=False):
... if verbose:
... print("Let me just say,", end=" ")
... print(arg)
...
>>> @fun.register(int)
... def _(arg, verbose=False):
... if verbose:
... print("Strength in numbers, eh?", end=" ")
... print(arg)
...
>>> @fun.register(list)
... def _(arg, verbose=False):
... if verbose:
... print("Enumerate this:")
... for i, elem in enumerate(arg):
... print(i, elem)
Once you've defined your function as such, you can call fun(something)
, and Python will find out the correct implementation (int
or list
here), of fallback to the default implementation def fun(...): ...
.
You therefore solely have to decorate your original function, and you're done, your users can add their own types.
Note: as pointed out in the comments, singledispatch
is already implemented in Python, it's pkgutil.simplegeneric