Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Slicing `a` (e.g. `a[1:] == a[:-1]`) create copies of the `a`?

A friend of mine showed me the following Python code:

a[1:] == a[:-1]

Which returns True iff all the items in a are identical.

I argued the code is hard to understand from first sight, and moreover - it is inefficient in memory usage, because two copies of a will be created for the comparison.

I've used Python's dis to see what happens behind the hood at a[1:]==a[:-1]:

>>> def stanga_compare(a):
...     return a[1:]==a[:-1]
...
>>> a=range(10)
>>> stanga_compare(a)
False
>>> a=[0 for i in range(10)]
>>> stanga_compare(a)
True

>>> dis.dis(stanga_compare)
  2           0 LOAD_FAST                0 (a)
              3 LOAD_CONST               1 (1)
              6 SLICE+1
              7 LOAD_FAST                0 (a)
             10 LOAD_CONST               2 (-1)
             13 SLICE+2
             14 COMPARE_OP               2 (==)
             17 RETURN_VALUE

It boils down to two slicing commands - SLICE+1 and SLICE+2. The documentation is unclear as to whether these opcodes actually create a new copy of a, or just a reference to it.

  • Does the SLICE commands copy a?
  • Does the answer varies between Python implementations (Cython, Jython)?

Update

This snippet is clearly unreadable and confusing, and I'm not going to ever use it in actual code. My interest is purely technical - whether slicing copies the list, and whether the answer varies under different circumstances.

like image 892
Adam Matan Avatar asked Dec 08 '13 06:12

Adam Matan


1 Answers

The documentation is unclear because slicing different objects does different things. In the case of a list, slicing does make a (shallow) copy1. Note that this is a feature of python lists independent of python implementation. In the case of other objects (like numpy arrays), it might not create a copy.

If you want a better way to check that all the elements in a list are the same, I would probably recommend:

 all(lst[0] == item for item in lst)

From a performance standpoint, your friend's code might actually outperform this for small lists since list slicing is so optimized. But, this is IMHO much easier to tell what is going on and has the opportunity to "short circuit" as soon as it finds a non-match.

1The actual function to look at is list_subscript, but for most cases, it just calls list_slice

like image 152
mgilson Avatar answered Sep 22 '22 17:09

mgilson