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

4.7. One value can have multiple names

It is necessary to be careful when modifying mutable values such as lists because there may be more than one name bound to that value. Here is a demonstration.

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 seldom a problem in practice, but it is important to keep in mind that two or more names can be bound to the same value.

If you are concerned about modifying a list when other names may be bound to the same list, you can always make a copy using the slicing expression “L[:]”.

>>> L1 = ['bat', 'cat']
>>> L2 = L1
>>> L3 = L1[:]
>>> L1.append('hat')
>>> L2
['bat', 'cat', 'hat']
>>> L3
['bat', 'cat']