List getting extended when assigned to itself

Discussion in 'Python' started by Krishnan Shankar, Aug 25, 2013.

  1. Hi Python Friends,

    I came across an example which is as below,
    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,
    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
     
    Krishnan Shankar, Aug 25, 2013
    #1
    1. Advertisements

  2. 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 |



    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]

    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 D'Aprano, Aug 25, 2013
    #2
    1. Advertisements

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments (here). After that, you can post your question and our members will help you out.