Python List Assignment Caveat

The Problem

In Python, the assignment operator (=) assign the reference to the list instead of making copy of it. The following interaction will demonstrate this concept:

>>> original = [1,2,3]
>>> reference = original # assign the reference
>>> reference
[1, 2, 3]
>>> reference.append(4)
>>> reference
[1, 2, 3, 4]
>>> original
[1, 2, 3, 4]
>>>
  • In line 1, we create a new list, original, with three elements.
  • In line 2, we assign this list to a new variable, reference.
  • In line 5, we append a new value to reference.
  • What happens to the original list? Line 8 and 9 might bring shock to those who are new to Python. What happened?

The answer is the assignment in line 2 assigns the reference to the list so both original and reference will now share the same list and that changes made to one will reflect in the other. So, how do we really make copy of the list instead of sharing the reference?

The Solutions

To make a new copy of a list, there are two different approaches: using the list() function and using the sub list mechanism. The following interactive session will demonstrate the list() function:

>>> original = [1,2,3]
>>> copy = list(original)
>>> copy.append(4)
>>> copy
[1, 2, 3, 4]
>>> original
[1, 2, 3]
>>> 

In line 2, we use the list function to create a copy of the original and assign that list to the variable copy. Any action on copy at that point on will not affect the original list (line 6 and 7)

The following interactive session will demonstrate the sub list feature:

>>> original = [1,2,3]
>>> copy = original[:]
>>> copy.append(4)
>>> copy
[1, 2, 3, 4]
>>> original
[1, 2, 3]
>>> 

Discussion

while both methods accomlish the same goal, many argues that the sub list method is faster. However, the list() function wins point for being easier to understand, especially to new comers.

About these ads

7 thoughts on “Python List Assignment Caveat

  1. Brendan Miller

    It’s not just lists. Assignment in python is always by reference. It’s just that many objects in python are immutable (strings, tuples, numbers), so there isn’t any functional difference between a copy and a reference.

    x = (1,2)
    y = x
    id(x) == id(y)

    id returns the address of the objects. They are always the same after assignment.

  2. Taylor McKay

    There is a third way to do create copies in Python: the copy module.


    >>> from copy import copy
    >>> l = [1,2,3]
    >>> c = copy(l)
    >>> l.append(4)
    >>> c
    [1, 2, 3]

    Although this is much slower than the previous methods you illustrated.

    >>> t = Timer("c = copy(l)", "from copy import copy; l = [1,2,3]")
    >>> t.timeit()
    1.339083194732666
    >>>
    >>> t = Timer("c = list(l)", "l = [1,2,3]")
    >>> t.timeit()
    0.3724050521850586
    >>>
    >>> t = Timer("c = l[:]", "import copy; l = [1,2,3]")
    >>> t.timeit()
    0.1694178581237793

    From those timings, it’s clear that doing l[:] is the fastest. If we wanted to do a deep copy (copy the objects in our list for instance), we could use the copy module’s deepcopy.

  3. paul

    how can i do for having that behaviour using only the = ? using the metaclass
    l=list()
    l.append(1)
    l.append(2)
    l.append(3)
    l1=l
    l1[2] = ’B’
    print(l1)
    [1, 2, ’B’]
    print(l)
    [1, 2, 3

  4. Pingback: Class and instance variables in Python 2.7 | TimothyAWiseman – SQLWise

  5. Hai Post author

    @paul: I don’t understand your question. I suggest to use stackoverflow.com if you still need some help.

  6. Danny

    Thanks I was encountering this problem yesterday. Now I understand what was going wrong with my code.

    Thanks for a clear and simple explanation

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s