68

I've got a list that I create a copy of in order to do some manipulations while still keeping the original list. However, when I set copy_list equal to org_list, they become the same thing, and if I change copy_list, org_list changes too. For example:

org_list = ['y', 'c', 'gdp', 'cap']

copy_list = org_list

copy_list.append('hum')

print(copy_list)
print(org_list)

returns

['y', 'c', 'gdp', 'cap', 'hum']
['y', 'c', 'gdp', 'cap', 'hum']

I don't know too much about what is actually going on but it looks like org_list is actually passing itself to copy_list so that they are actually the same thing.

Is there a way to make an independent copy of org_list without doing something clumsy like:

copy_list = []
for i in org_list:
    copy_list.append(i)

I say this because I have the same problem with other types of variables, for example a pandas dataframe.

LotusUNSW
  • 2,027
  • 18
  • 20
natsuki_2002
  • 24,239
  • 21
  • 46
  • 50
  • 5
    Assignments in Python *do not* create new objects - an assignment merely establishes a binding between a [variable] name and an object. That should explain everything, without talking about "references". – user2864740 Nov 13 '13 at 10:56

4 Answers4

91

That is because in python setting a variable actually sets a reference to the variable. Almost every person learning python encounters this at some point. The solution is simply to copy the list:

copy_list = org_list[:] 
Nathaniel Ford
  • 20,545
  • 20
  • 91
  • 102
yuvi
  • 18,155
  • 8
  • 56
  • 93
  • 14
    I just spend the past 3 hours trying to debug my program... I thought I was going mad. This was the most infuriating bug I have EVER ran into. Wow... – 43.52.4D. Mar 17 '16 at 07:05
  • 18
    @43.52.4D. Only it's not a bug :-) – yuvi Mar 17 '16 at 07:13
  • 2
    @yuvi what if its a two dimensional array? – Sachin Singh Sep 14 '17 at 09:11
  • 3
    @SachinSingh then you need to loop-copy, because a matrix is actually a list of references. Copying that list does not mean copying the references as well (which makes sense). Though that's not a very common situation (I can't think of any reason why you'd ever need to do it to be honest) – yuvi Sep 23 '17 at 13:56
  • 16
    If you have a list of objects, you need to do a "Deep Copy" instead: `import copy new_list = copy.deepcopy(old_list)` – JohnB Nov 01 '18 at 15:25
  • you can use copy method for copy data : -> copy_list = org_list.copy() – Prajit Karande Sep 10 '19 at 10:10
21

When you write

org_list = ['y', 'c', 'gdp', 'cap']

you create the list object, and give it the name "org_list".

Then when you do

copy_list = org_list

you just mean, "the name copy_list refers to the same object as org_list does".

If your list only contains immutable types, then you can create a copy by

copy_list = list(org_list)

But note that this is only valid if the list objects are immutable, because it creates a SHALLOW copy, i.e. the list is copied, but every element on the list is not duplicated.

If you have i.e. a list of lists and want EVERYTHING to be duplicated, you need to perform a DEEP copy:

import copy
org_list = ['y', 'c', ['gdp', 'rtd'], 'cap']
copy_list = copy.deepcopy(org_list)
Roberto
  • 2,696
  • 18
  • 31
19

This is just copying the reference

copy_list = org_list

you should use

copy_list = org_list[:]    # make a slice that is the whole list

or

copy_list = list(org_list)
John La Rooy
  • 295,403
  • 53
  • 369
  • 502
11

Variable names in python are references to the original. To actually make a copy, you need to be explicit:

import copy

copy_list = copy.copy(org_list)
Andrew Jaffe
  • 26,554
  • 4
  • 50
  • 59