Well, OK – sure it’s a side-effect, but it’s an intended and clearly defined side effect – it’s an mutating method.
But it’s not a “hidden side-effect”.
Also while the definition there is: " side effect if it has any observable effect other than its primary effect of reading the value of its arguments and returning a value to the invoker of the operation."
But the examples are all of hidden side effects, not mutating methods.
And that’s why the mutating methods all return None. To make this clear to the user.
Thinking a bit more – I’m not sure it’s desirable or possible to make all mutating methods atomic, but extend() could be implemented something like:
That is, build a full list first, and then extend the list. Though that would require an extra copy of the list – so probably not a performance hit worth taking for this purpose.
Or, I suppose, keep track of how many elements were there to begin with, and then roll it back if there’s an Exception:
def extend(self, iterable):
start_len = len(self)
try:
for item in iterable:
self.append(item)
except Exception as err:
del self[start_len:]
raise ValueError("Iterable failed before completion") from err
if implemented in C, that would have very little overhead in the usual case.
But I doubt the core devs would think this was a precaution worth taking.
So not only is it not worth doing for reasons of effort and complexity – it’s a breaking change for very little gain.
It’s pretty clear that the only action needed is a very minor doc update to either remove the misleading sentence or to make it “roughly equivalent to”.
I’ll let anyone who wants race me for the small glory of submitting the PR. You’ve got a few hours while I’m offline…
Is there better wording we could use? Often we want to describe a feature in terms of another, but they aren’t exact equivalents. How do we make it clear without twisting ourselves in knots?
Oh, you didn’t miss anything.
I was getting at the fact that just because it’s unspecified doesn’t mean that there isn’t some or even quite a lot of code relying upon it.
Changing it might be allowed by Python’s backward compatibility policy, but given how long the behavior has been there, changing it would demand a reasonably strong rationale.
Doesn’t “similar to” do the trick?
`x.extend(ys)` is similar to `x[len(x):] = ys`
They aren’t equivalent, but they are similar.
I intend to dig up the relevant tutorial doc and open that PR now, with this wording, and link to this thread. If the reviewers dislike it, they can always reject the change – “we should debate at length until we find perfect wording” would be a rational position to take, but it’s not one I agree with at all.
IMO, there is absolutely zero value in comparing it with the slice syntax in any way, especially for beginners, the primary target of this document. The goal here is to tell them about extend - comparing it with a for-append loop makes sense since those are more basic things they might be familiar with. In contrast, this more advanced and niche usage of the slice notation is not something thar is going to help them understand extend, most likely it will just confuse them.
So I think either drop that part of the sentence completely or replace it as suggested by @elis.byberi. (in the latter case adding a “roughly” or “almost” in case there are some subtle differences)
I also agree: I wouldn’t explain things the way that the doc does, in terms of slices.
However, it is easier to review a very small change of wording than a change of content. Maybe I’m being too hasty, but I believe that we’re better off with suggestions on the doc at this point. It is at least a simple and direct approach. Either cpython#125343 is a good suggestion or it isn’t.
It was a list in version 1.6 but was changed to an iterable in version 3.7
The fact that this tutorial predates generators makes it outdated since version 2.2. I don’t see any other cases, aside from generators, that would cause this difference in behavior. (They are equivalent, not merely similar.)
That said, the best approach would be to provide beginners with a hint about the evaluation order when using generators, in particular. This way, extend is free to change its behavior in future releases. (I’m not suggesting that extend should change its behavior.)
That was the only way to understand extend in my day—through trial and error.