0

I'm calling a function in Python 3.7.x and passing a list to it. I do not want the list modified. Inside the function, I make a copy of the list and modify that.

After the function completes, the original list passed to the function has been modified. Why is that happening and how can I prevent it?

Here is the code

def append_string(alist, astring):
    a_new_list = alist
    a_new_list.append(astring)
    return a_new_list
my_list = ["a", "b"]
my_string = "c"
my_new_list = append_string(my_list, my_string)
print(my_list)
print(my_new_list)

Here is the output. Notice that my_list has been modified.

['a', 'b', 'c']
['a', 'b', 'c']

I would have expected my_list to remain unmodified and the my_new_list to contain the concatenation of the values.

Tennis Smith
  • 451
  • 6
  • 14

2 Answers2

1

a_new_list = alist doesn't make a copy of the list, it just adds a new name reference to the same list.

To copy the list you can choose from a couple of options

a_new_list = alist[:]

from copy import copy
a_new_list = copy(alist)

Edit

After writing this I looked and there is a duplicate question here: How to clone or copy a list?. The accepted answer there is much better and more detailed and lists more options that I didn't actually know about.

Jacinator
  • 1,413
  • 8
  • 11
  • You should note that using `copy` creates a shallow copy. For 1-d lists of numbers, this is not a problem. But it will be a problem if you have a list of lists. Ex: `a=[0]; b=[a]; c=copy(b)`. Then `c is b` returns False (as expected), but `c[0] is b[0]` returns True --> The internal list is **not** copied. If this is an issue, use `copy.deepcopy` instead. – SyntaxVoid Oct 25 '19 at 14:18
0

Let me try,

In your function, you take a list and an object as input. After you append the item to provided input, you return back the list.

What is happening is,

  1. you are sending a list's C pointer to the function
  2. you add an item to the list
  3. you are returning the list's C pointer

>>> def append_string(alist, astring):
...     a_new_list = alist
...     a_new_list.append(astring)
...     print(id(a_new_list)) # print the list's id
...     return a_new_list
...
>>>
>>> alist = ['a', 'b', 'c']
>>> id(alist)
140215330632840
>>>
>>> 
>>> append_string(alist, 'd') # this 
140215330632840
['a', 'b', 'c', 'd']
>>>
>>> id(append_string(alist, 'd'))
140215330632840
140215330632840
>>>

As you see, the id of the list is just moving in and out of the function. To have an exact copy of the list, you can use deepcopy function in python inbuilt library copy

Note: id function - Return the identity of an object. This is guaranteed to be unique among simultaneously existing objects.

sam
  • 1,819
  • 1
  • 18
  • 30