4 ms·
I didn't know what "Single Dispatch Functions" was all about. Sounded very abstract. But it's actually pretty cool: http://www.python.org/dev/peps/pep-0443/ ht
by pixelmonkey 13y ago
I didn't know what "Single Dispatch Functions" was all about. Sounded very abstract. But it's actually pretty cool:
http://www.python.org/dev/peps/pep-0443/ http://www.python.org/dev/peps/pep-0443/
What's going on here is that Python has added support for another kind of polymorphism known as "single dispatch".
This allows you to write a function with several implementations, each associated with one or more types of input arguments. The "dispatcher" (called 'singledispatch' and implemented as a Python function decorator) figures out which implementation to choose based on the type of the argument. It also maintains a registry of types -> function implementations.
This is not technically "multimethods" -- which can also be implemented as a decorator, as GvR did in 2005[1] -- but it's related[2].
Also, the other interesting thing about this change is that the library is already on Bitbucket[3] and PyPI[4] and has been tested to work as a backport with Python 2.6+. So you can start using this today, even if you're not on 3.x!
[1] http://www.artima.com/weblogs/viewpost.jsp?thread=101605 http://www.artima.com/weblogs/viewpost.jsp?thread=101605
[2] http://en.wikipedia.org/wiki/Dynamic_dispatch http://en.wikipedia.org/wiki/Dynamic_dispatch
[3] https://bitbucket.org/ambv/singledispatch https://bitbucket.org/ambv/singledispatch
[4] https://pypi.python.org/pypi/singledispatch https://pypi.python.org/pypi/singledispatch
- Pxtl 13y agoWait, so it's language-supported external polymorphism? That's...odd, since external polymorphism is considered an anti-pattern by OOP pl purists.
- omaranto 13y agoWhy is that odd? I don't think the Python community is mostly OOP purists.
- seanmcdirmid 13y agoWhich OOP PL purists specifically think language-supported external polymorphism is an anti-pattern? Do you have any citations?
- voltagex_ 13y agoThis is quite useful to hide away casting from one type to another or to "build" objects - say you have an object represented by a JSON or XML structure, now you can have functions that accept either/or. Is this method overloading or am I missing something?
- revelation 13y agoIt looks like overloading, but overloading as it is typically understood in languages like C++ is weaker: http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch_is_more_than_function_overloading http://en.wikipedia.org/wiki/Double_dispatch#Double_dispatch...
- yareally 13y agoNot directly replying, but more amending your comment. Double dispatch is generally simulated with imperative languages via the Visitor Pattern. Generally used when you have objects that won't change their structure very much (and are backed by an interface of some sort [also needed for the polymorphism aspect of the pattern]), but have to do lots of various manipulations with them. That way, you don't have to change the interface each time you add another method. Also referred to as "inversion of control." I used it before for filesystem type objects and for walking over the structure of an XML file (though both times were for school related projects). I could probably dig up the labs and post them on my Github for anyone interested. It's pretty cool how it works (and sort of hard to wrap one's head around initially), but not something I would consider using often. Scala has a unique take on double dispatch[1][2] for being a hybrid imperative/functional language. [1] http://stackoverflow.com/questions/8618082/visitor-pattern-in-scala http://stackoverflow.com/questions/8618082/visitor-pattern-i... [2] http://blog.nirav.name/2009/04/how-scalas-pattern-matching-can-replace.html http://blog.nirav.name/2009/04/how-scalas-pattern-matching-c...
- revelation 13y agoHuh? But that's not single dispatch? Single dispatch is deciding what function to call based on the type of your object, not on the type of arguments. That's called double dispatch. Single dispatch is pretty standard polymorphism, C++ can do that.
- pixelmonkey 13y agoThat's a bit of a semantic argument. Python already has "object-oriented single dispatch" -- aka traditional object-oriented polymorphism. What this module adds is "functional single dispatch". So, whereas before you'd always be forced to implement some type-varying function using two classes `HandleA` and `HandleB`, each with an implementation for `handle`: class HandleA: def handle(self): pass class HandleB: def handle(self): pass def main(obj): # obj could be instance of HandleA or HandleB obj.handle() In this case, "dynamic dispatch" is done by `obj.handle()`, which will pick a different implementation depending on the type of obj. With this PEP/stdlib addition, you can now write two functions, `handle_A` and `handle_B`, which take an argument, `obj`, and are dynamically dispatched using the generic function `handle`. from functools import singledispatch @singledispatch def handle(obj): pass @handle.register(A) def handle_A(obj): pass @handle.register(B) def handle_B(obj): pass def main(obj): # obj could be instance of A or B handle(obj) And in this case, "dynamic dispatch" is done by `handle(obj)`, or really, by the dispatcher decorator. It chooses `handle_A` or `handle_B` based on the type of the `obj` argument The reason this is a nice addition is because it makes Python eminently "multi-paradigm" -- you can choose object-oriented or functional styles depending on your taste and the applicability to the task at hand, instead of being forced into one programming style or the other. (the content of my comments got long enough that I decided to document them for posterity over on my blog: http://www.pixelmonkey.org/2013/10/20/singledispatch http://www.pixelmonkey.org/2013/10/20/singledispatch)
- yeukhon 13y agoInteresting, but I have a hard time accepting this. If I accept a type of iterable I would either check isinstance and do separate methods or check isinstance and convert to a single type and operate on it. On the other hand, I also try to minimize accepting multiple types of iterable. I don't do that very often except in the case of list and tuple. Since these two types are very very similar in nature I call a separate method in my code to handle the two types. That's okay, just a few extra lines. I don't really understand the benefit of mm and dispatch. This sounds useful for building routes in webapp. But for library, it sounds like we are bringing back C++'s single interface, multiple types... I don't even remember what that is called.
- Walkman 13y agoFrom PEP 443: "In addition, it is currently a common anti-pattern for Python code to inspect the types of received arguments, in order to decide what to do with the objects."