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.

    Krishnan Shankar, Aug 25, 2013
    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

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

    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

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

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