0

I have a list and I want to understand slices of it. I take a slice [0:1] of it:

>>> l=[1,2,3,4]
>>> id(l[0])
140079803522784
>>> id(l[0:1][0])
140079803522784

They are the same. But:

>>> l[0]=7
>>> l
[7, 2, 3, 4]
>>> l[0:1][0]=13
>>> l
[7, 2, 3, 4]

So the slice's 0-element is the same as the list's 0-element, but when I change it in the slice, it is not changed in the list. Why not?

ericj
  • 2,138
  • 27
  • 44
  • 3
    Slicing creates a shallow *copy*... – Jon Clements Nov 05 '17 at 11:29
  • 3
    Because slicing makes a new list. – Daniel Roseman Nov 05 '17 at 11:29
  • Now try the same thing with arbitrary objects (a custom class for example) instead of integers (which are immutable). Your mind will be blown. – DeepSpace Nov 05 '17 at 11:30
  • @DeepSpace I did that. Same thing: >>>l=[[1,2],[1,3]] >>> l[0:1][0]=[7] >>> l [[1, 2], [1, 3]] – ericj Nov 05 '17 at 11:33
  • In your first example, `l[0]` and `l[0:1][0]` are nothing more than elements of `l`, specifically they are the first element, i.e. the number `1`. They have no association with the original list. – Tom Karzes Nov 05 '17 at 11:35
  • Ah, now I see it. `l[0:1]` is another list. It's first element equals the first element of `l`, but I did not modified that element. I replaced it, so I changed the `l[0:1]` list. Thanks. – ericj Nov 05 '17 at 14:07

1 Answers1

0

From the documentation:

All slice operations return a new list containing the requested elements. This means that the following slice returns a new (shallow) copy of the list.

So basically when you do l[0:1][0] = 13 you're assigning 13 as the value in a new list, not l. It's the same as if you did

[l[0]] = 13

or

g = [l[0]]
g[0] = 13

Note this is only true for immutable types, such as int and str. Since a slice performs a shallow copy, you'd get the behavior you'd expect if you modify an object.

>>> l = [{'hi': 7}, {}, {}, {}]
[{'hi': 7}, {}, {}, {}]
>>> l[0:1][0]['hi'] = 1
>>> l[0]
{'hi': 1}
jpyams
  • 4,030
  • 9
  • 41
  • 66
  • It is a copy, yes, but the elements in the copy refer to the same elements as the original list. Also if I do `l[0:1]=[13]`, `l` is changed. – ericj Nov 05 '17 at 11:39
  • 1
    @ericj they do, but integers are immutable. And your second example is explicit slice assignment, of course `l` gets changed. – jonrsharpe Nov 05 '17 at 11:40
  • @jonrsharpe Well, I tried with mutable lists: `l=[[1,2],[1,3]];l[0:1][0]=[7]`. Then `l` is `[[1, 2], [1, 3]]`. – ericj Nov 05 '17 at 11:45
  • That example is **not** slice assignment. It's assigning by index into the *result* of a slice, effectively `m = l[0:1]; m[0] = [7]`. It's only slice assignment when the *last* index is a slice. – jonrsharpe Nov 05 '17 at 11:46
  • Ah, now I see it. `l[0:1]` is another list. It's first element equals the first element of `l`, but I did not modified that element. I replaced it, so I changed the `l[0:1]` list. Thanks. – ericj Nov 05 '17 at 14:06