
On Sep 5, 2019, at 02:15, Chris Angelico <rosuav@gmail.com> wrote:
On Thu, Sep 5, 2019 at 7:08 PM Andrew Barnert via Python-ideas <python-ideas@python.org> wrote:
On Sep 4, 2019, at 20:51, Inada Naoki <songofacandy@gmail.com> wrote:
And you’re right, because int|str _looks_ better than (int, str) here, many people will be encouraged to use it even though it’s slower, which could potentially be a bad thing for some programs.
That's exactly my point. If we say "you can use `isinstance(x, int | str)` for now", people may think it is a new and recommended way to write it.
Right; I was agreeing, and saying it may even be worse than you’re suggesting. There’s always the possibility that any shiny new feature looks like the One True Way and gets overused. But in this case, it looks more obviously right even to someone who’s not interested in shiny new features and has never heard the word “pythonic” or read a new version’s release notes. So they’re going to use it. Which means if they run into a situation where they’re checking types of a zillion objects, they’re definitely not going to guess that it’s 5x as slow, so there definitely going to misuse it.
Hang on hang on.... what's this situation where you're checking types of a zillion objects?
Exception was the first one I thought of, but, as you argue, that’s a bit of a special case. And my next thought was the kind of thing you’d do with pattern matching in a different language but which would be more naturally (and often more efficiently) done with method calls (or maybe @singledispatch) in Python. But here’s an example from the stdlib, in the json module: Deep inside the recursive encoder function, there’s a string of `elif isinstance(value, …):` calls. And at least one of them does a check with a tuple today (to special-case list and tuple for encoding as JSON arrays without needing to call any user callbacks). In a JSON structure with zillions of nodes, this check will happen zillions of times—once for every node that’s a list or tuple or any type that gets checked after those types. This isn’t the most compelling example. Most nodes are probably captured before this check, and the ones lower on the chain are all the ones that are inherently slow to process so the added cost of getting there is less important, and so on. Plus, the very fact that the author thought of optimizations like that implies that the author would have had no problem profiling and replacing `list|tuple` with `(list, tuple)` if it makes a difference. But the fact that I found an example in the stdlib in 2 minutes of searching implies that this probably isn’t nearly as rare as you’d at first expect.