0

Consider the Python code below:

def change_list(in_list):
    in_list = [1,2,3]

def change_list_append(in_list):
    in_list.append(7)


my_list = [1,2,3,4,5,6]

change_list(my_list)
print(my_list)

change_list_append(my_list)
print(my_list)

The output is:

[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]

I don't understand why the first call (change_list) did not result in my_list to become [1,2,3]. Can someone explain? Look at what happens with the call to change_list_append: number 7 is appended to my_list.

kevin811
  • 31
  • 7
  • In the first function you create a variable `in_list` with the scope inside a function; in the second function you simply append new value to already existent list – Anvar Kurmukov Aug 24 '20 at 13:37
  • The difference is, when you type `in_list = [1,2,3]` you create a new variable with the same name (as in global scope), however when you type `in_list.append(7)` you mutate (change) already existent list. – Anvar Kurmukov Aug 24 '20 at 13:42
  • @AnvarKurmukov Strictly speaking, you aren't creating a new variable; the parameter `in_list` is already a local variable, and you are just assigning a new value to it. – chepner Aug 24 '20 at 13:43
  • Does this answer your question? [Passing values in Python](https://stackoverflow.com/questions/534375/passing-values-in-python) or https://stackoverflow.com/questions/986006/how-do-i-pass-a-variable-by-reference. The key sentence there is: *If you pass a mutable object into a method, the method gets a reference to that same object and you can mutate it to your heart's delight, __but if you rebind the reference in the method, the outer scope will know nothing about it__, and after you're done, the outer reference will still point at the original object.* – Tomerikoo Aug 24 '20 at 13:51

3 Answers3

0

Assigning to a name never changes the value previously referenced by the list. This is true even without invoking function parameters.

>>> x = [1,2,3]
>>> y = x
>>> y = [4,5,6]
>>> x
[1, 2, 3]

Changing what y refers to does not alter what x refers to.


In your second example, you are invoking a mutating method on the list referenced by the parameter. Both my_list and in_list refer to the same list, so it any changes made to the list via either reference are visible from either reference.

See https://nedbatchelder.com/text/names.html for a more in-depth discussion of how references work in Python.

chepner
  • 497,756
  • 71
  • 530
  • 681
0

I think this post sums it up nicely => Why can a function modify some arguments as perceived by the caller, but not others?

You can assign items to the in_list using methods (like the .clear() method or the .assign() ) not rename.

Tom Dierckx
  • 666
  • 6
  • 12
0

As mentioned by others, the 1st function does not modify the global my_list. Instead it modifies the local variable

If you want change_list to modify the global variable you need to the function to return the new value and assign it to my_list.

Something like this will do:

def change_list():
    newList = [1,2,3]
    return newList

def change_list_append(in_list):
    in_list.append(7)


my_list = [1,2,3,4,5,6]

my_list = change_list()
print(my_list)

change_list_append(my_list)
print(my_list)

Output:

[1, 2, 3]
[1, 2, 3, 7]
Mr. Discuss
  • 355
  • 1
  • 4
  • 13