Reputation: 53
I have a simple example. The function test_list_change should change the list passed to it as a parameter. And inside this function there is a call to sub-routine test_list_change_2 which should change the same list.
The problem is, that the result list doesn't contain changes made by the test_list_change_2 subroutine
Why it could be?
Here is the example:
def test_list_change(lst):
if len(lst) < 3:
lst.append("the last one")
test_list_change_2(lst)
def test_list_change_2(lst):
lst = ["the very last one"]
string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
The output:
['first', 'another one', 'the last one']
Upvotes: 0
Views: 126
Reputation: 718
You probably got confused how things work in python with "passing by reference" and thought that since it is passed by reference, so the original list should be updated to ["the very last one"].
It works in the following manner:
1) before test_list_change is called, there is a name "string_list" and python creates a object ["first", "another one"] which is assigned to string_list
2) now in test_list_change, a new name "lst" is assigned with ["first", "another one"]. So now both names are assigned with the same object. It is then appended and changed to ['first', 'another one', 'the last one'], pointed by both string_list and lst
3) In test_list_change_2, before you do the assignment, there exist another local lst name which points to ["first", "another one", 'ths last one']. Then python creates another object ['the vary last one'] and replaces the value of the local lst variable.
4) string_list still points to ['first', 'another one', 'the last one']
So another way to put it, variables are just names passed around and objects are managed 'by reference'.
Upvotes: 1
Reputation: 116
If you are trying to get just "the very last one" to be in the list then:
def test_list_change(lst):
if len(lst) < 3:
lst.append("the last one")
lst = test_list_change_2(lst)
def test_list_change_2(lst):
for i in range(len(lst)):
lst.pop()
lst.append("the very last one")
string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
Upvotes: 0
Reputation: 180481
You need to actually change the original list/object
:
def test_list_change(lst):
if len(lst) < 3:
lst.append("the last one")
test_list_change_2(lst)
def test_list_change_2(lst):
lst[:] = ["the very last one"] # changes original list object
string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
['the very last one']
If you want to change around the elements:
def test_list_change_2(lst):
lst[:-1] = ["the very last one"]
lst[:] = lst[::-1]
string_list = ["first", "another one"]
test_list_change(string_list)
print (string_list)
['the last one', 'the very last one']
You can manipulate the list whatever way you like but you need to actually refer to the original list object, reassigning a name won't change the lst it will just assign that name to another object.
Upvotes: 3
Reputation: 107347
You need to return ["the very last one"]
in test_list_change_2
:
def test_list_change_2():
return ["the very last one"]
and assign the result of function to lst
in first function :
def test_list_change(lst):
if len(lst) < 3:
lst.append("the last one")
lst= test_list_change_2()
Note that actually you dont need a function here !!! you can do this assignment in the firs function .
Upvotes: 0
Reputation: 2392
Your test_list_change2
procedure is doing lst = ['the very last one']
. It's simply assigning a new object to the local name lst
. It has no effect whatsoever on the list passed in to that procedure.
I'm not sure what you're trying to accomplish. If you want test_list_change2
to add to lst
, just append it. Can you clarify?
Upvotes: 0