That’s exactly my point. When you ask for a native list in Python, you are specifically writing a program that has the functionality of using a list of possibly any type of object. You’re asking for that heterogeneous type flexibility, either because you need it or the overhead doesn’t matter in your case. But either way, by writing that Python program you are saying, “I’d like all this stuff Python gives me.”
If you want to write a totally different program, say using a contiguous memory array of a homogeneous type, then you write something different, like with the array.array class, or numpy, or wrap your own thing in Cython.
That is the thing whose functionality you’d compare to C/C++, because the functionality goals would be similar.
But writing an algorithm that expects tight contiguous memory array operations (or bare metal structs, etc.) in pure Python, it would just be a strawman that is not meaningfully comparable to similar C++ code.
I don't think so, since I meant "the same functionality as the user visible functionality" -- not that of the language.
>You’re asking for that heterogeneous type flexibility, either because you need it or the overhead doesn’t matter in your case. But either way, by writing that Python program you are saying, “I’d like all this stuff Python gives me.”
That's irrelevant to the end user though. You could argue that Python makes it faster to deliver the program (which is a win for the end user), but if the program is ultimately slower and more frustrating, the user might have preferred a faster version, if he was given the chance, even if that meant paying more or waiting more to get it.
This still misses the point. If the goal was always to produce a fast program because the end user wanted speed, then why were you ever writing that pure Python version to start with? If you planned to compare it to a language with native support for some performance-critical aspect, why wouldn’t you have used the facilities that Python provides for those same performance goals?
If we want to compare the speed of two horses, A and B, and Horse A can either wear fast shoes or sparkly shoes, while Horse B only has fast shoes, then what good is a speed comparison between sparkly-shoed A and fast-shoed B? We wanted speed the whole time. Putting a known-suboptimal thing in there would just be a strawman.
In a nutshell, because none of those facilities are really designed for writing your whole program in. If you have a program whose runtime is dominated by a few very hot functions, probably numerical, then numpy, Numba, and Cython are all decent options for making those functions fast, and you can use the full power of Python for the rest of your code. But if you have a big fat codebase where just about everything is lukewarm – and that describes a lot of programs – then you need everything to be fast. It's certainly possible to write a whole program in Cython, using static C types for everything and minimizing interaction with the Python world, but … well, nobody does that. As in, I've never seen a single large pure-Cython codebase, though I wouldn't be surprised if some exist.
I’m not sure how this is related to its parent comment thread, but in any case I agree with it, and would view this as supporting my point.
In my experience, a big lukewarm codebase is exceedingly rare, and often gets that way because there was premature optimization in the form of assuming the project had to be written in this or that language way back at the beginning, without there ever having been a prototype stage when multiple implementation languages were actually tested. And even given that, it takes a special kind of alignment of the stars for the usage patterns, resource limits, and language tools to all work out properly for a system with few hotspots.
But regardless, I do agree there are plenty of cases when it can be the right choice to presume a need to write the whole thing in C/C++.
Examples become irrelevant though when they try to do a horse race comparison of a contrived, unoptimized Python example with a C/C++ example that would be more optimal out of the box just due to intended differences in the languages. Because these examples are exactly like targeted hotspot optimization, which would be the case when Python augmented with Cython/numba is a stronger contender.
>This still misses the point. If the goal was always to produce a fast program because the end user wanted speed, then why were you ever writing that pure Python version to start with?
Tons of reasons. Some companies will opt for what's fashionable -- e.g. Electron SPA's today. Or with what's cheaper to churn out. Or have their users locked in and could not care less, just use what's cheapest and fastest to get something out.
Sure, but for the purposes of a blog post that’s supposed to shine a light on performance considerations in specific, contrived examples, it would be a strawman. Yet that’s the setting where you see a lot of people write e.g. a naive double loop algorithm in Python and criticize its performance compared with “the same” double loop algorithm in C.
It’s an uninformative comparison precisely because they are not “the same.” Pure Python looping (iterators) and doing pure Python operations in the loop body (run time type dynamics implicitly assumed to be needed/desired, heterogeneous container types of PyObject references assumed to be needed/desired) is conceptually a different thing than loops in C (simple increments) and, say, operations on a contiguous memory array, regardless of whether the syntax looks superficially similar to invite a visual comparison.
If you want to write a totally different program, say using a contiguous memory array of a homogeneous type, then you write something different, like with the array.array class, or numpy, or wrap your own thing in Cython.
That is the thing whose functionality you’d compare to C/C++, because the functionality goals would be similar.
But writing an algorithm that expects tight contiguous memory array operations (or bare metal structs, etc.) in pure Python, it would just be a strawman that is not meaningfully comparable to similar C++ code.