Next / Previous / Contents / TCC Help System / NM Tech homepage

4.6. A list surprise

Now it is time for one of Python's little surprises. The author has found Python pretty predictable for the most part, but there are some behaviors that might surprise programmers familiar with other languages. Here is one of them.

We start by creating a list of two strings and binding two names to that list.

>>> menu1 = menu2 = ['kale', 'tofu']
>>> menu1
['kale', 'tofu']
>>> menu2
['kale', 'tofu']

Then we make a new list using a slice that selects all the elements of menu1:

>>> menu3 = menu1 [ : ]
>>> menu3
['kale', 'tofu']
      

Now watch what happens when we modify menu1's list:

>>> menu1.append ( 'sardines' )
>>> menu1
['kale', 'tofu', 'sardines']
>>> menu2
['kale', 'tofu', 'sardines']
>>> menu3
['kale', 'tofu']

If we appended a third string to menu1, why does that string also appear in list menu2? The answer lies in the definition of Python's assignment statement:

To evaluate an assignment statement of the form

V1 = V2 = ... = expr

where each Vi is a variable, and expr is some expression, first reduce expr to a single value, then bind each of the names vi to that value.

So let's follow the example one line at a time, and see what the global namespace looks like after each step. First we create a list instance and bind two names to it:

>>> menu1=menu2=['kale', 'tofu']

Two different names, menu1 and menu2, point to the same list. Next, we create an element-by-element copy of that list and bind the name menu3 to the copy.

>>> menu3 = menu1[:]
>>> menu3
['kale', 'tofu']

So, when we add a third string to menu1's list, the name menu2 is still bound to that same list.

>>> menu1.append ( 'sardines' )
>>> menu1
['kale', 'tofu', 'sardines']
>>> menu2
['kale', 'tofu', 'sardines']

This behavior is not often a problem in practice, but it is important to know that two or more names can be bound to the same value.