9 Replies - 692 Views - Last Post: 20 November 2012 - 10:30 AM Rate Topic: -----

#1 jerryoak  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 20-April 12

Behavior of lists in Python

Posted 18 November 2012 - 05:23 PM

I'm having some trouble using lists in python.

I enter a list and make a copy of it. I evaluate the copy and make changes to it and as a check I compare it to the original list.
It seems that the original list is being changed as well.

base_var = 5
working_var = base_var
print base_var, working_var

working_var = 6
print base_var, working_var
print


base_list = [0,1,2]
working_list = base_list
print base_list, working_list

working_list[1] = 3
print base_list, working_list
print


two_d_list = [[1,2], [3,4]]
two_d_copy = two_d_list
print two_d_list, two_d_copy

two_d_copy[1][1] = 10
two_d_copy = two_d_list
print two_d_list, two_d_copy



In the above code the integer variables behave as I expect:
5,5 then 5,6 is printed.

The lists and the 2-d lists don't:
[0, 1, 2] [0, 1, 2]
[0, 3, 2] [0, 3, 2]

and
[[1, 2], [3, 4]] [[1, 2], [3, 4]]
[[1, 2], [3, 10]] [[1, 2], [3, 10]]

is printed.

Is there a way to define the working lists to have them be independent of the original lists?

Thanks

Is This A Good Question/Topic? 0
  • +

Replies To: Behavior of lists in Python

#2 darek9576  Icon User is offline

  • D.I.C Lover

Reputation: 198
  • View blog
  • Posts: 1,692
  • Joined: 13-March 10

Re: Behavior of lists in Python

Posted 18 November 2012 - 05:44 PM

[:] <---
Was This Post Helpful? 0
  • +
  • -

#3 Simown  Icon User is offline

  • Blue Sprat
  • member icon

Reputation: 319
  • View blog
  • Posts: 650
  • Joined: 20-May 10

Re: Behavior of lists in Python

Posted 18 November 2012 - 05:50 PM

Yeah, as you can probably tell you are referencing the same list with different names. What you want to do is make a copy of the list.

>>> l1 = [1,2,3]
>>> l1
[1, 2, 3]
>>> l2 = l1[:]
>>> l2
[1, 2, 3]
>>> 
>>> l2.append(4)
>>> l1
[1, 2, 3]
>>> l2
[1, 2, 3, 4]



The important line is l2 = l1[:], this means copy l1 from the start index to the end index (all of it).

Or you could do it a little less cryptically with list comprehension:
>>> l1 = [1,2,3]
>>> l2 = [i for i in l1]
>>> l2
[1, 2, 3]
>>> l2.append(4)
>>> l1
[1, 2, 3]
>>> l2
[1, 2, 3, 4]


Was This Post Helpful? 0
  • +
  • -

#4 Python_4_President  Icon User is offline

  • D.I.C Regular

Reputation: 53
  • View blog
  • Posts: 321
  • Joined: 13-August 11

Re: Behavior of lists in Python

Posted 18 November 2012 - 06:08 PM

You can wrap the original in a list() statement to create a new list independent of the one referenced by the original.


original = [1, 2, 3, 4]
copy = list(original)




See help(list)

Help on class list in module __builtin__:

class list(object)
 |  list() -> new empty list
 |  list(iterable) -> new list initialized from iterable's items
 |  


This post has been edited by Python_4_President: 18 November 2012 - 06:12 PM

Was This Post Helpful? 0
  • +
  • -

#5 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7872
  • View blog
  • Posts: 13,350
  • Joined: 19-March 11

Re: Behavior of lists in Python

Posted 18 November 2012 - 06:29 PM

the list() function is probably the best way to do this, but be careful: both [:] and list() make shallow copies. Here's what this means:

>>> l = [[1,2],[3,4],[5,6]]
>>> l2= l[:]
>>> l3= list(l)
>>> l1
>>> l
[[1, 2], [3, 4], [5, 6]]
>>> l2
[[1, 2], [3, 4], [5, 6]]
>>> l3
[[1, 2], [3, 4], [5, 6]]
>>> l2[0][0]=9
>>> l3[0][1]=8
>>> l2[1]="foo"
>>> l3[2]="bar"
>>> l
[[9, 8], [3, 4], [5, 6]]
>>> l2
[[9, 8], 'foo', [5, 6]]
>>> l3
[[9, 8], [3, 4], 'bar']
>>> 




Notice that if I change a direct element of l2 or l3, ie, l2[1]="foo", this is not a problem: it does what you expect. However, if I change an element of one of the sublists I find that they're still references to the same objects, and so everything pointing to that sublist is now pointing to the changed sublist.

These are called aliasing bugs, because l2[0] is just an alias for l[0]. Can be embarrassing.

EDIT: I don't mean to imply that this doesn't happen with the listcomp method of copying, it does. I don't know if there's an idiomatic method of doing deep copies.

This post has been edited by jon.kiparsky: 18 November 2012 - 06:31 PM

Was This Post Helpful? 1
  • +
  • -

#6 Nallo  Icon User is offline

  • D.I.C Regular
  • member icon

Reputation: 163
  • View blog
  • Posts: 255
  • Joined: 19-July 09

Re: Behavior of lists in Python

Posted 18 November 2012 - 06:41 PM

Think of Python "variables" as a name with an arrow pointing to some object.
Here a and b are just names for the same object, the list [1, 2, 3]:
a = [1, 2, 3]
b = a


So, when you alter a you also alter b.

As mentioned by others you can copy lists. But the methods shown there only make shallow copies. If the elements of the list are mutable objects themselves you still have the same problem (even with that shallow copy)
two_d_list = [[1,2], [3,4]]
two_d_copy = two_d_list[:]
print two_d_list, two_d_copy

two_d_copy[1][1] = 10
two_d_copy = two_d_list
print two_d_list, two_d_copy



You would need a deepcopy:
import copy

two_d_list = [[1,2], [3,4]]
two_d_copy = copy.deepcopy(two_d_list)



Though I cannot remember the last time I really needed to do that. When you think you need it chances are you misdesigned your program.

Edit: oops, jon.kiparsky beat me on the comment on shallow coopies. And yes there is a method for deepcopies ... but it is slow(costly) and best avoided.

This post has been edited by Nallo: 18 November 2012 - 06:43 PM

Was This Post Helpful? 3
  • +
  • -

#7 Simown  Icon User is offline

  • Blue Sprat
  • member icon

Reputation: 319
  • View blog
  • Posts: 650
  • Joined: 20-May 10

Re: Behavior of lists in Python

Posted 18 November 2012 - 06:42 PM

It seems you can do deep copies easily with the copy module! I didn't know it existed until now though.

>>> import copy
>>> l1 = [1,2,3]
>>> l2 = copy.deepcopy(l1)
>>> l2
[1, 2, 3]



Ah, beaten to posting by Nallo!

This post has been edited by Simown: 18 November 2012 - 06:43 PM

Was This Post Helpful? 1
  • +
  • -

#8 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7872
  • View blog
  • Posts: 13,350
  • Joined: 19-March 11

Re: Behavior of lists in Python

Posted 18 November 2012 - 07:04 PM

Good stuff. Thanks to you both - it's nice that I only have to wonder aloud and y'all come across with the answer!
Was This Post Helpful? 0
  • +
  • -

#9 jerryoak  Icon User is offline

  • New D.I.C Head

Reputation: 0
  • View blog
  • Posts: 4
  • Joined: 20-April 12

Re: Behavior of lists in Python

Posted 20 November 2012 - 10:28 AM

Thanks for all the replies, they have been a great help,
JerryOak
Was This Post Helpful? 0
  • +
  • -

#10 jon.kiparsky  Icon User is offline

  • Pancakes!
  • member icon


Reputation: 7872
  • View blog
  • Posts: 13,350
  • Joined: 19-March 11

Re: Behavior of lists in Python

Posted 20 November 2012 - 10:30 AM

Glad to help.
Was This Post Helpful? 0
  • +
  • -

Page 1 of 1