Search code examples
pythonfunctoolspep

Python: official guidance on using single dispatch functions


I just learned about the @singledispatch operator from functools. My first thought was that I would now be using this everywhere, because I write functions like this a lot. But I have been using Python for a couple years now and had never encountered this before, which is scary.

Why aren't other people using this everywhere? Are there expensive tradeoffs that I am somehow missing?

Is there some kind of official guidance on when to use or not use @singledispatch?


Solution

  • The singledispatch decorator is just one of the several approaches to implement polymorphism, and while it's widely used in languages such as Clojure via multimethods, it just happens not to be so common in Python land.

    In OOP oriented languages you may generally see polymorphism applied at the class level, where an object defines a method and it's derived subclasess tweak the behavior of it. This in turn is a form of singledispatch which is implicit in the class type of the object i.e. the implementation is dispatched in terms of the self argument rather than the actual method input arguments.

    Another popular way to apply polymorphism is what I would call "duck polymorphism". To clear things out an example of this would be the pop method of lists and dictionaries. In this example both objects implement the same method at an abstract behavioral level, the methods remove things to the collection, they share the core idea but the implementations are different and there's no class hierarchy between them. In some sense they're analogous to interfaces but in less strict sense, you quack like a duck so I can treat you like so without code breaking.

    All in all it seems that other ways to achieve the same behavior are more used and in the end it all depends on how the developers like to structure their code.

    Back to the other questions, I (naively) wouldn't say there's a huge performance penalty using the decorator though surely there are further lookups and function calls involved compared to calling one func straight away.

    With regards to official suggestions a good read is PEP 443. Therein you'll find an historical overview of why this was added to the language.


    EDIT: Some important corrections made by Miyagui.

    1. Dictionaries doesn't have an append method.
    2. File-like objects actually subclass from a base object.
    3. Print doesn't dispatch on arguments type, rather it calls str or repr methods of the arguments. Indeed the example of singledispatch in the PEP was pprint.pprint, not print.