6

I would like to ask you for help about the behaviour of a slicing operator in Python.

  1. On the one hand we know that L[:] creates a shallow copy of the list L. To verify it one can just print id(L), id(L[:]) and notice that they are different.
  2. On the other hand we know that del L[:] removes references from the original object. It makes the original list empty - not the shallow copy of it. Of course I agree that creating a shallow copy, then removing references from it, would make little sense so I understand that here we want to operate on the original list.

Is there any rule saying when slicing operator creates a shallow copy and when it doesn't? How can I know it without manually testing it?

I searched for this and found these topics:

but unfortunately they do not answer my question, at least I do not see it.

Community
  • 1
  • 1
Drizzt
  • 143
  • 7
  • "Is there any rule saying when slicing operator creates a shallow copy and when doesn't?" Yes. It always creates a shallow copy. – kindall Feb 16 '16 at 18:46
  • 3
    The behaviour of `del L[:]` is independent of that of `L[:]` because the former translates to `list.__delitem__(slice)` while the latter is `list.__getitem__(slice)`. You can verify this by creating a class with `__getitem__` and `__delitem__` and then getting and deleting a slice. – Sergei Lebedev Feb 16 '16 at 18:47
  • 2
    In Python, `L[:]` calls `L.__getitem__`, while `del L[:]` calls `L.__delitem__`. In other words, `del` completely changes meaning of the statement. – GingerPlusPlus Feb 16 '16 at 18:48
  • First of all thanks Vincent for editing my post. Right after sending it I edited it and tried to make it better, but you were so quick I didn't make it in time. – Drizzt Feb 16 '16 at 18:51

1 Answers1

7

del L[:] is a distinct operation from accessing L[:], which is again a distinct operation from L[:] = x.

  • del L[:] calls __delitem__ on the object with a slice object.
  • L[:] calls __getitem__ with that slice object.
  • L[:] = x calls __setitem__ with the slice object and x.

These three operations can be implemented in very different ways, depending on what the object is. For built-in list types, __delitem__ erases the items specified in the slice, __setitem__ replaces the items with the items given, and __getitem__ returns a new (copied) list consisting of the elements specified.

However, not all objects have to behave this way. For example, with a NumPy array, __getitem__ with a slice returns a view of the array rather than a copy - modifying the view alters the original array.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • Thanks nneonneo for your help. Your answer exactly concerns what I needed to know to understand what is happening in this case. – Drizzt Feb 17 '16 at 07:52