List slice assignment with resize using negative indices

Viewed 157

If I do this:

p=list(range(10))
p[2:6:1]=['a','b']

I get p=[0, 1, 'a', 'b', 6, 7, 8, 9] which means Python is replacing the the elements indexed 2-5 with the new list ['a','b'].

Now when, I do

p=list(range(10))
p[-2:-6:-1]=['a','b']

Python says ValueError: attempt to assign sequence of size 2 to extended slice of size 4

Why does it resize the list in the first case but not the second?

4 Answers

This is expected behavior for extended slices. As you have discovered, it requires the same number of elements to be assigned to the slice. Here's documentation that refers to the issue.

It becomes more obvious why if instead you sliced p[1:5:2]. It's not a nice contiguous block that you can easily resize.

p[2:6:1] works because it's essentially a regular slice, ie p[2:6].

I don't know the exact inner working of python list slicing, but it probably has something to do with the fact that p[-2:-6:-1] works backwards through the list instead of forwards.

If you want a quick fix, use: p[-6:-2:1] = ['a', 'b']

That way, you'll work from 'left to right' again.

According to the documentation, an assignment to a regular slice (you first one) can be used to change the length of the sequence, while extended slices aren't this flexible.

When assigning to an extended slice, the list on the right hand side of the statement must contain the same number of items as the slice it is replacing.

Maybe because ['a', 'b'] propagated forward, but your indexing of '-1' forces it to propagate backwards.

You could do the same using:

p[-6:-2:1] = ['a', 'b']

But if you want increase the length from 10 to 12, you could try this:

p[-2:-6:1]=['a','b']

or:

p[-2:-6]=['a','b']

This both will give:

[0, 1, 2, 3, 4, 5, 6, 7, 'a', 'b', 8, 9]
Related