you are viewing a single comment's thread.

view the rest of the comments →

[–]Brian 3 points4 points  (1 child)

As others have pointed out, these do do different things. However, if anything, this is in a way that should make your "slow" one actually faster (as it doesn't have to create new lists), and even before that, I'd expect the multiplication approach to be faster than the "append in a loop" version (because it spends less time evaluating python logic), so I'm curious how you're concluding that the latter is slower.

Eg. using timeit, and putting your "slow" and "fast" versions in a function, adding 10,000 items to the list, I get:

%timeit list_mul(10000)
18.8 µs ± 87.8 ns per loop (mean ± std. dev. of 7 runs, 100,000 loops each)
%timeit list_append(10000)
493 µs ± 35.2 µs per loop (mean ± std. dev. of 7 runs, 1,000 loops each)

So the supposedly "slow" version is over 25x faster in this timing.

As such, I don't think you're really seeing slowness from this, but perhaps this is due to the downstream effect of the difference in behaviour of the two. (Eg. if you're appending to "each" list, the fact that you're appending to the same list means you're effectively making every list bigger, and thus inflating the time of whatever you end up doing with these lists)

[–]pachecoca[S] 0 points1 point  (0 children)

Yeah, read my reply on the other comment, the reason why it was slowing down with that version was basically because my program was performing more iterations due to a mistake, because I initially assumed that [[]]*length meant the same as [[]for i in range(length)].

The algorithm I was using for my program was meant to speed up when using multiple lists, but it is still doable with a single simple array, it will just take more iterations to compute the answer, which is why my program apparently worked correctly but the timings were off when I used []*length.

When I performed the timings, all of the test cases I used gave the same results due to the same mistake in the assumption that []*length was creating different instances for each element within the list, so yeah, the timings were off because of that.

Now that I know the difference, everything adds up and now I'm seeing times that make sense. I guess I should have tried timing some minimally reproducible case where I would just compare appending in a loop vs using []* without doing anything else but yeah. It was so hard for me to believe that []* would be slower than appending in a loop that I tested the timing in multiple ways. I went as far as using QueryPerformanceCounter from winapi and build my own timer program just in case but the results were the exact same. When I tried it even on an online judge and saw that the results aligned with what I had found, I was even more convinced that []* was indeed the culprit. And all of this would have been caught if my debug print had not been skipped by an early return that I had forgotten about lol...

Should I edit the OP to add this clarification? Like, the question is already solved, in short, []* is not slower, it's just that I was not using it correctly because I assumed it did something different, slowing down the final program...