Velocity Reviews > Syntax: pointers versus value

# Syntax: pointers versus value

Danny Castonguay
Guest
Posts: n/a

 07-30-2003
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,

Tino Lange
Guest
Posts: n/a

 07-30-2003
On Wed, 30 Jul 2003 12:46:43 -0400, Danny Castonguay
<(E-Mail Removed)> wrote:

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

Danny Castonguay
Guest
Posts: n/a

 07-30-2003
Tino Lange wrote:
> 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,

Tino Lange
Guest
Posts: n/a

 07-30-2003
On Wed, 30 Jul 2003 13:46:29 -0400, Danny Castonguay
<(E-Mail Removed)> wrote:

>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

John J. Lee
Guest
Posts: n/a

 07-30-2003
Danny Castonguay <(E-Mail Removed)> writes:

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

[...]
> 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.

[...]

http://www.python.org/doc/FAQ.html#4.38

John

John Hunter
Guest
Posts: n/a

 07-30-2003
>>>>> "Danny" == Danny Castonguay <(E-Mail Removed)> writes:

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

 Thread Tools

 Posting Rules You may not post new threads You may not post replies You may not post attachments You may not edit your posts BB code is On Smilies are On [IMG] code is On HTML code is OffTrackbacks are On Pingbacks are On Refbacks are Off Forum Rules

 Similar Threads Thread Thread Starter Forum Replies Last Post cerr C Programming 12 04-07-2011 11:17 PM Peter Potamus the Purple Hippo Firefox 0 05-08-2008 12:56 PM Paul Butcher Ruby 12 11-28-2007 06:06 AM Russ ASP .Net 1 06-10-2004 03:06 AM Matthew Louden ASP .Net 1 10-11-2003 07:09 PM

Advertisments