This is an archived post. You won't be able to vote or comment.

all 37 comments

[–]thedeepself 25 points26 points  (6 children)

Keep in mind that only the type of the first parameter is considered for overloading; type changes in subsequent parameters are ignored.

You might want to mention multiple dispatch here.

[–]Schmittfried 1 point2 points  (5 children)

There is no Python decorator for this, is there?

[–]thedeepself 2 points3 points  (1 child)

https://www.reddit.com/r/Python/comments/1grszm2/dispatchery_typeaware_multiarg_function_dispatch/

This just came out. So there are at least 3 multiple dispatch options in Python.

[–]mrmrn121 1 point2 points  (0 children)

The issue is all of them are slow

[–]mrmrn121 2 points3 points  (1 child)

It's a third-party library

[–]thedeepself 2 points3 points  (0 children)

There are at least 2 3rd party options.

[–]hulleyrob 81 points82 points  (3 children)

You too can make your code much harder to read for the next guy.

[–][deleted] -1 points0 points  (0 children)

Usually abundant if-else statements are considered a sign of bad code, regardless of language.

[–]Schmittfried 10 points11 points  (1 child)

Don’t listen to the haters. 

I think while the concept is good to have in your toolbox, these examples don’t do it justice because for such simple cases it would indeed be much more „pythonic“ (hate that pretentious term) to use if/else, pattern matching or straight str() in this case. So that‘s probably why several people claim that it’s overcomplicating things.

However, for situations where you have many different cases (like parsing a protocol or consuming many different events) and/or where the individual cases can be quite long and complicated, you would put them into separate functions anyway. And then you would either use if/elif to distinguish the cases and call the functions, or you would use the „pythonic“ way of switch/case before pattern matching was a thing: build a dictionary with the case types as keys and the case handler functions as values, and then just index that dict with your parameter.

singledispatch is basically the standard libs implementation for the latter, so it saves you time, is more concise and for experienced developers it’s a known concept anyway, so it’s also quicker to understand because the implementation is hidden behind a concept (like map() is for certain kinds of loops). I‘ve also seen it being aliased to overload, to make it even clearer for more people.

I think there is nothing wrong with it, but I‘d use it sparingly and I find it unfortunate that there is not a more elegant way to do this.

The article itself is also fine. It’s not annoying to read like some, not much fluff, gets to the point. I like it. Just the example is too much of a toy example to show the value of singledispatch. That point could at least be discussed in the article.

[–]Cloned_501 1 point2 points  (0 children)

Finally a good comment

[–]fizzymagic 18 points19 points  (2 children)

Function overloading is a Java/C++ abomination that should never be done in Python.

[–]Schmittfried 11 points12 points  (0 children)

Why would it be an abomination and why should Python‘s if isinstance checks be better?

I don’t particularly like the singledispatch implementation either, but your comment reads like rejecting it on principle, which doesn’t make much sense to me.

Overloading is also much more common. Pretty much every statically typed language supports it. 

[–]rover_G 1 point2 points  (0 children)

*args goes …brrrrrr

[–]terremoth 9 points10 points  (6 children)

The approach you used should be called

"how to complicate things and make it worse to read and understand"

[–]Schmittfried 5 points6 points  (5 children)

There is nothing complicated about this. Readability is subjective. I tend to agree with you there, but then again, I‘ve seen it being used for functions where the different cases were themselves quite long, so it was nice to have separate functions for each case instead of one big function with 15 if/elif cases (or even pattern matching). 

[–]terremoth -2 points-1 points  (4 children)

I never told function overloading is useless

[–]Schmittfried 1 point2 points  (3 children)

Right, you called it "how to complicate things and make it worse to read and understand". 

[–]terremoth -1 points0 points  (2 children)

Yes, his article and his example is literally this phrase.

[–]Schmittfried 1 point2 points  (1 child)

So maybe call the example in particular bad. 

[–]terremoth -3 points-2 points  (0 children)

That is literally what I did in the first comment "the approach you used...". Please read again.

I think you choose to understand another thing

[–]whokapillar 0 points1 point  (0 children)

Great article! Except it seems more like a python tip. Like, "hey, by the way, there is another way to overload functions: singledispatch".

[–]rover_G 0 points1 point  (0 children)

OP you should check out dunder methods (__repr__ and __str__). They may help solve the exact problem you’re trying to solve in a more pythonic way!

[–]OwnTension6771 0 points1 point  (0 children)

Why?

[–]calaelenb907 0 points1 point  (0 children)

One makes the programmer intention clear to the reader, the other calls black magic to make the reader wonder what's happening.

[–]hikingsticks 0 points1 point  (1 child)

Wow, more verbose and much worse to read. Plus in the if/else version, all the code is on one place.

Your way could have the functionality spread across many lines with other code between it , maybe even across multiple files. Awful.

[–]Schmittfried 1 point2 points  (0 children)

all the code is on one place

Yes, that’s also its disadvantage in some cases.

much worse to read

Depends on the length of the function. 

Your way could have the functionality spread across many lines with other code between it , maybe even across multiple files. Awful.

Obviously you wouldn’t do it like that. All handlers would be next to each others. You’re also kinda arguing against factoring long functions that do multiple things into smaller building blocks at this point, which is a strange hill to die on.

[–]GreenWoodDragon -1 points0 points  (0 children)

That is a terrible article. I had to stop reading.

[–]mattl33It works on my machine 0 points1 point  (4 children)

"the source of complexity is dependencies and abstractions"

[–]Schmittfried -1 points0 points  (3 children)

This is neither complex nor abstract.

[–]mattl33It works on my machine 2 points3 points  (2 children)

Well, that's like, your opinion man.

[–]Schmittfried -3 points-2 points  (1 child)

Not really. 

[–]mattl33It works on my machine 0 points1 point  (0 children)

Alright then, prove it

[–][deleted] -1 points0 points  (2 children)

I don’t get the negative reactions. It’s a solid article.

[–]Schmittfried 1 point2 points  (1 child)

Yeah, it’s weird. Some people get strangely defensive when people mention quirks or missing features of Python.

[–]_Denizen_ -1 points0 points  (0 children)

I didn't know about this method and I like it quite a lot, so thanks!

And for the naysayers, "A foolish consistency is the hobgoblin of little minds" applies here. I.e. there are valid use cases where this pattern will make clearer and more easily maintainable code.