List mutation and shared structure
Lists are mutable data structures, which defines that we can actually modifies the values stored in their components. We do this by using element-selection statement, like a[1] on the left-hand side of an assignment expression. So, the assignment
a[1] = -3
assigns the second element of a to be -3. In more detail, the left-hand side of this expression
We have permanently modified the list named a.
We will defines the consequences of the mutability of lists; programs that change list structure can become very confusing, but you can always work your way through what is happening by drawing out the memory diagrams.Continuing the previous samples, let us remind that a is bound directly to a pointer to a list (or a sequence of memory cells), and think about what occurs if we do:
Now, we can reference parts of the list through b, and even modifies the list structure that way:
>>> b[0]
2
>>> b[2] = 1
Notice that, because a and b point to the similar list, modifying b changes a!
This situation is called aliasing : the name b has become an alias for a. Aliasing may be useful, but it may also cause problems, because you can inadvertently modify b (by passing it into a procedure that changes one of its structured statement, for example) when it is very important to you to keep a unmodi?ed.
Another important way to change a list is to add or change components. We will show adding elements to the end of a data structure, but look the Python documentation for more functions on lists. This statement
memory sequence), b is modified too. This is a side effect of the aliasing between a and b:
>>> b
[2, -3, 1, 9]
Often, it will be important to make a fresh copy of a list so that you can change it without affecting the original one. Here are two similar types to make a copy (use whichever one you can remember):
>>> c = list(a)
>>> c = a[:]
Here is a sample of the memory at this position:
Now, if we change a component of c, it does not affect a (or b!):
>>> c[0] = 100
>>> c
[100, -3, 1, 9]
>>> a
[2, -3, 1, 9]
We can create crazy lists that share file within a single list:
>>> f = [1, 2, 3]
>>> g = [1, f, [f]]
If you want to add an element to a list and get a new copy at the similar time, you may do
>>> a + [1]
The + operator makes a new list that contains the elements of both of its arguments, but does not give any top-level files. All of our functions of copying only work reliably if your lists do not have other lists, because it only copies single level of list. So example, if we did:
It is clear that if we were to modify f, it would alter h, so this is not a completely fresh copy. If you have to copy deep structures, that is, to create a copy not only of the top level list structure, but of the lists of any structures that list has, and the lists those lists has, etc., you will have to use the Python copy.deepcopy method.