Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.python > #52962 > unrolled thread

List getting extended when assigned to itself

Started byKrishnan Shankar <i.am.songoku@gmail.com>
First post2013-08-25 09:22 +0530
Last post2013-08-25 05:31 +0000
Articles 2 — 2 participants

Back to article view | Back to comp.lang.python


Contents

  List getting extended when assigned to itself Krishnan Shankar <i.am.songoku@gmail.com> - 2013-08-25 09:22 +0530
    Re: List getting extended when assigned to itself Steven D'Aprano <steve+comp.lang.python@pearwood.info> - 2013-08-25 05:31 +0000

#52962 — List getting extended when assigned to itself

FromKrishnan Shankar <i.am.songoku@gmail.com>
Date2013-08-25 09:22 +0530
SubjectList getting extended when assigned to itself
Message-ID<mailman.206.1377402755.19984.python-list@python.org>

[Multipart message — attachments visible in raw view] — view raw

Hi Python Friends,

I came across an example which is as below,

>>> var = [1, 12, 123, 1234]
>>> var
[1, 12, 123, 1234]
>>> var[:0]
[]
>>> var[:0] = var
>>> var
[1, 12, 123, 1234, 1, 12, 123, 1234]
>>>

Here in var[:0] = var we are assigning an entire list to the beginning of
itself. So shouldn't it be something like,

[[1, 12, 123, 1234], 1, 12, 123, 1234]

It happens when we do the below,

>>> var = [1, 12, 123, 1234]
>>> var[0] = var
>>> var
[[...], 12, 123, 1234]
>>>

Literally var[0] = var and var[:0] = var almost meens the same. But why is
the difference in output? Can anyone explain what happens when
slicing assignment and direct assignment.

Regards,
Krishnan

[toc] | [next] | [standalone]


#52966

FromSteven D'Aprano <steve+comp.lang.python@pearwood.info>
Date2013-08-25 05:31 +0000
Message-ID<521996c3$0$29986$c3e8da3$5496439d@news.astraweb.com>
In reply to#52962
On Sun, 25 Aug 2013 09:22:27 +0530, Krishnan Shankar wrote:

> Hi Python Friends,
> 
> I came across an example which is as below,
> 
>>>> var = [1, 12, 123, 1234]
>>>> var
> [1, 12, 123, 1234]
>>>> var[:0]
> []
>>>> var[:0] = var
>>>> var
> [1, 12, 123, 1234, 1, 12, 123, 1234]
>>>>
>>>>
> Here in var[:0] = var we are assigning an entire list to the beginning
> of itself. So shouldn't it be something like,
> 
> [[1, 12, 123, 1234], 1, 12, 123, 1234]

No, you have misunderstood how slicing works. When you assign to a slice, 
you *replace* the existing slice with items from the other list:


py> L = [1, 2, 3, 4, 5]
py> L[2:4] = [None, None, None]
py> L
[1, 2, None, None, None, 5]


Notice that it does not insert the list [None, None, None] as a single 
item.

If the slice you replace is empty, this is equivalent to inserting the 
items:

py> L = [1, 2, 3, 4, 5]
py> L[2:2] = [None, None, None]
py> L
[1, 2, None, None, None, 3, 4, 5]

The beginning of the list is just an empty slice: L[:0] means "all the 
items, starting at the beginning of the list, and finishing *before* 
index zero". So that makes it an empty slice, and items are inserted 
after the start of the list but before index zero:


py> L = [1, 2, 3, 4, 5]
py> L[:0] = [None, None, None]
py> L
[None, None, None, 1, 2, 3, 4, 5]


So assigning to a slice *always* extends. If you try to assign a single 
value, not inside a list or other iterable, it fails:

py> L = [1, 2, 3, 4, 5]
py> L[:0] = None
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can only assign an iterable


Remember that indexes in Python are *before* the item, so when slicing, 
Python cuts at the vertical lines | as shown below:

| a | b | c | d | e | f | g |

The vertical lines are numbered 0 through 7, and the slice [2:5] cuts as 
shown:

| a | b | c | d | e | f | g |
0---1---2---3---4---5---6---7

[2:5] => | c | d | e |



> It happens when we do the below,
> 
>>>> var = [1, 12, 123, 1234]
>>>> var[0] = var
>>>> var
> [[...], 12, 123, 1234]


Here you are *not* assigning to a slice, but setting a single item. The 
item at position 0 is replaced with the contents of var, which happens to 
be the same list, but that is just a distraction. It is more clear when 
you use a different value:

py> L = [1, 2, 3, 4, 5]
py> L[0] = "something"
py> L
['something', 2, 3, 4, 5]


> Literally var[0] = var and var[:0] = var almost meens the same. 

No, they are very different.

Even though the difference is a single character, var[:index] and 
var[index] are very different, no matter what the value of index. The 
first is a slice ending at index, the second is a single item at index.

The same naturally applies to var[index:] as well, which is a slice 
starting at index.

If you wish to insert a sequence as a single object, you have two 
choices: you can use the list insert() method, or you can wrap the 
sequence in a list, and then use slice assignment:


py> L = [1, 2, 3, 4, 5]
py> L[2:4] = [L]
py> L
[1, 2, [...], 5]


-- 
Steven

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.python


csiph-web