Syntax: pointers versus value

D

Danny Castonguay

Simple question but I can't find the answer. Using an example:

listA = [1 ,2]
listB = listA
listB.append(3)
#listA now is [1,2,3]

I want to avoid listA's value to change. Clearly, "listB = listA"
creates the problem. listB and listA become two pointers to the same
object. How then, do I duplicate the two objects; ie make a copy of the
object that listA is pointing to and have listB point to that object.

I'm new to python and I love it.

Thank you,
 
T

Tino Lange

On Wed, 30 Jul 2003 12:46:43 -0400, Danny Castonguay

Hi!
Clearly, "listB = listA"
creates the problem. listB and listA become two pointers to the same
object.
Exactly.

How then, do I duplicate the two objects; ie make a copy of the
object that listA is pointing to and have listB point to that object.

Use:
listB = listA[:]

Cheers,

Tino
 
D

Danny Castonguay

Tino said:
Use:
listB = listA[:]

--------------------------------------------------------------------
In the example I have given, it does solve the problem. However, for
some reason I don't understand, it doesn't work in the next example:

def ps_of_missing_edges(initial_graph, missing_edges):
num_m_e = len(missing_edges) #number of missing_edges
num_e_pset = 2**num_m_e
graphs = []
for i in range(0,num_e_pset): #iteration will stop at 2^num-1
temp_i = i #use temp_i to find i's bit values
new_graph = initial_graph[:]
print 'initial_graph is ' + str(initial_graph)
for j in range (0,num_m_e):
if temp_i%2 == 1:
new_graph[missing_edges[j][0]-1].append(missing_edges[j][1])
temp_i = temp_i >> 1
graphs.append(new_graph)
return graphs

--------------------------------------------------------------

the output when I call:
ps_of_missing_edges([[2,3],[1],[1]], [[2,3],[3, 2]])
is:
initial_graph is [[2, 3], [1], [1]]
initial_graph is [[2, 3], [1], [1]]
initial_graph is [[2, 3], [1, 3], [1]]
initial_graph is [[2, 3], [1, 3], [1, 2]]

--------------------------------------------------------------
Therefore, somehow initial_graph's value changes even though the
assignment is new_graph = initial_graph[:]

Assuming that the assignment does it's job, then I don't see how
initial_graph's value changes.


Thank you,
 
T

Tino Lange

new_graph = initial_graph[:]
initial_graph is [[2, 3], [1], [1]]
initial_graph is [[2, 3], [1], [1]]
initial_graph is [[2, 3], [1, 3], [1]]
initial_graph is [[2, 3], [1, 3], [1, 2]]

Hi!

Now you have lists in lists. This is another situation.

new_graph = initial_graph[:] will really make a copy of the outer list
- but this outer list contains no values but once again pointers to
other objects.

Use the copy-module for nested copy things like that:
http://www.python.org/doc/current/lib/module-copy.html

Cheers,

Tino
 
J

John Hunter

Danny> I want to avoid listA's value to change.

There are several ways

listB = listA[:]

listB = [x for x in listA]

import copy
listB = copy.copy(listA)
listB = copy.deepcopy(listA)

These don't all do the same thing, but all satisfy the example you
posted, eg
>>> listA = [1 ,2]
>>> listB = listA[:]
>>> listB.append(3)
>>> listA
[1, 2]

So far so good, but consider this case
>>> listA = [[],1]
>>> listB = listA[:]
>>> listB[0].append(12) # changing the list at listB[0]
>>> listB [[12], 1]
>>> listA
[[12], 1]

Sneaky, eh? So the 'listB = listA[:]' made a copy of the list, but
not of the elements of the list. This is a shallow copy, and you
should get the same behavior from copy.copy.

Note that this is related to mutable and immutable objects in python.
In the example above, I didn't replace the first item of the list, I
changed it. Since both listA and listB contained the same object as
their first element, changing one changes the other. If I had
replaced that object in listB, nothing would have happened to listA
>>> listA = [[],1]
>>> listB = listA[:]
>>> listB[0] = 12 # replacing the object, not changing it
>>> listB [12, 1]
>>> listA
[[], 1]


If you want to avoid this, use deepcopy.
>>> import copy
>>> listA = [[],1]
>>> listB = copy.deepcopy(listA)
>>> listB[0].append(12)
>>> listB [[12], 1]
>>> listA
[[], 1]

The behavior of mutable objects bites everyone a few times when they
begin learning python, so welcome to the club!

John Hunter
 

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. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,767
Messages
2,569,572
Members
45,046
Latest member
Gavizuho

Latest Threads

Top