Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Slice in python - is it a copy or just a pointer?

Tags:

python

list

slice

>>> a = [3, 2]
>>> a[0:1][0] = 1
>>> a
[3, 2]

>>> a[0:1] = [1]
>>> a
[1, 2]

What does a[0:1] mean?

  1. If it's a pointer to the range of a, then a[0:1][0] = 1 should change the value of a.
  2. If it's a copy of the range of a, then a[0:1] = [1] shouldn't change the value of a.

I think the result of the two is inconsistent with each other. Could you please help me work out the problem?

like image 709
cstur4 Avatar asked Apr 12 '14 10:04

cstur4


People also ask

Is a Python slice a copy?

The short answer. Slicing lists does not generate copies of the objects in the list; it just copies the references to them. That is the answer to the question as asked.

Does slice create a copy?

The slice() method is a copying method. It does not alter this but instead returns a shallow copy that contains some of the same elements as the ones from the original array.

What does slice () do in Python?

Python slice() Function The slice() function returns a slice object. A slice object is used to specify how to slice a sequence. You can specify where to start the slicing, and where to end. You can also specify the step, which allows you to e.g. slice only every other item.

What is a slice in a list Python?

In short, slicing is a flexible tool to build new lists out of an existing list. Python supports slice notation for any sequential data type like lists, strings, tuples, bytes, bytearrays, and ranges. Also, any new data structure can add its support as well.


1 Answers

Internally, this is a big difference:

>>> a = [3, 2]
>>> a[0:1][0] = 1

is a shorthand for

temp = a[0:1]
temp[0] = 1

and is internally expressed as

a.__getitem__(slice(0, 1)).__setitem__(0, 1)

resp.

temp = a.__getitem__(slice(0, 1))
temp.__setitem__(0, 1)

so it accesses a part of the list, making a separate object, and doing an assignment on this object, which is then dropped.

On the other hand,

>>> a[0:1] = [1]

does

a.__setitem__(slice(0, 1), [1])

which just operates on the original object.

So, while looking similar, these expressions are distinct on what they mean.

Let's test that:

class Itemtest(object):
    def __init__(self, name):
        self.name = name
    def __repr__(self):
        return self.name
    def __setitem__(self, item, value):
        print "__setitem__", self, item, value
    def __getitem__(self, item):
        print "__getitem__", self, item
        return Itemtest("inner")

a = Itemtest("outer")
a[0:1] = [4]
temp = a[0:1]
temp[0] = 4
a[0:1][0] = 4

outputs

__setitem__ outer slice(0, 1, None) [4]
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4
__getitem__ outer slice(0, 1, None)
__setitem__ inner 0 4
like image 69
glglgl Avatar answered Sep 19 '22 02:09

glglgl