I wrote this software only as a test to see how far can I push Python. I DO NOT intend to use it in a production environment, nor do I advice anyone of doing so - it is probably really slow, as the dispatch resolution is quite complex. I will not be responsible for anything happening due to use of this project. Read the BSD License for more information.


This is a package for multimethods, i.e. multiple dispatch for Python 3. Python 3 IS required as a new metaclass feature is used as well as annotations. Here is a very quick example of what is possible:

from multi import Multi

class Bar(metaclass = Multi):
    def what(self, y : str, z : int, x : str): return 5
    def what(self, y : object, z : str, x : str = "abc"): return x
    def what(self, y : str, z : str, x : str): return x + y + z

b = Bar()
assert b.what("b", x = "a", z = "c") == "abc"
assert b.what(z = "a", y = 8) == "abc"
assert b.what(z = "a", x = "b", y = 1) == "b"

The metaclass Multi should be used. After that, it is as simple as giving the annotations that you need. When no annotation is given, anything can go into that "slot". Otherwise, a subclass of the type given is expected. Dispatch is based on the "proximity" of the types of all arguments - that is, the smallest sum of "distances" between the types given and the types expected. For example, if we have:

def foo(self, x : int, y : object): pass
def foo(self, x : object, y : int): pass

And you try to call that with foo(1, 1) it is going to raise an AmbiguousCall exception, because the total "distance" for both calls is 1 (for the first method - for the first argument it is 0, because we pass an int and expect an int, and for the second argument it is 1, because we expect an object, but pass an int and there is only one step from int to object, i.e. object is int's base class). See the bigger example for a deeper insight. In short - static/classmethod are supported, default and keyword arguments are available too. If no overload is found in the current class, the base classes are checked in the same way Python does. Of course, there are ways to break this - e.g. if you you have classes A, B and C such that B inherits from A and C from B, and A and C have Multi as their metaclasses, and you try calling a method on C which has only an acceptable overload in A... but yes, you get the idea, you probably aren't going to do that anyway. :) Oh, and be careful when overloading some method with a static and non-static versions... being able to call staticmethods through an instance really causes confusion with overloaded methods. :)

Otherwise, everything should work as expected and should be pretty straight-forward and apparent. So, enjoy, and if you think of any way of making things better, let me know!

Last edited Apr 4, 2010 at 9:35 PM by Alien282, version 3


No comments yet.