Why operating with list gives different results?

So i was doing Jacobi algorithm to aproximate solutions of a system of equations and I encounter a couple things I don't undertand when working with list. Lets say i have this three functions

def func1 (list):
    list_old = list
    list[0] = 99

    print(list_old)
    print(list)

def func2 (list):
    list_old = list.copy()
    list[0] = 99

    print(list_old)
    print(list)

def func3 (list):
    list_old = list
    list = [9,9,9]

    print(list_old)
    print(list)

list = [0,0,0]
func1(list)
func2(list)
func3(list)

Func1 prints

[99, 0, 0] # List_old
[99, 0, 0] # List

Func2 prints

[0, 0, 0] # List_old
[99, 0, 0] # List

Func3 prints

[0, 0, 0] # List_old
[9, 9, 9] # List

So my questions are: 1) why List[0] at func1 modifies list_old? I think it's something with pointers and memory space, but i'm not sure and i didn't find anything that explain this. 2) Why in func3 list_old doesn't modifies? Shouldn't be the same like func1?

Upvotes: 0

Views: 63

Answers (2)

LBald
LBald

Reputation: 493

As @Dmitry point out about immutability and mutability, the list type, differently of other types in python is mutable, that means operations over lists change the list itself while other immutable objects, as strings, create new instances in memory when operated. The code below illustrates it better:

lstA = [0, 0, 0]
lstB = lstA
print(lstA is lstB) # True
# change list B
lstB[0] = 9
print(lstA is lstB) # keeps True
strA = "A string"
strB = strA
print(strA is strB) # True
# Change strB
srtB[0] = "B" # Ops! item assignment not supported (immutable object)
# Then let's do it in another way
strB = "B" + strA[1:] # strB = "B string"
print(strA is strN) # False (other string was created)

Upvotes: 0

Jay
Jay

Reputation: 35

Pretty much what @ggorlen said is spot on. The way python variables like lists work, is they are stored in a specific point in memory. By passing your list variable into a function, and then modifying it, you are modifying it at its specific address in memory so even when you leave the function func1 for example, you modified your original list and and calls to it will have those modifications.

What you are doing in func2 with .copy() is making another list at another point in memory. So, modifications to this list will not effect modifications to your original list and vice versa (anymore that is, the modifications in func1 will still be present in the new copied list because they were made before being copied).

Now, to answer your question, in func1 list_old is not the same list_old in func2, the variable name list_old is local to both functions func1 and func2 and pointing to different lists. list_old in func1 is pointing to the original list declared in your first line of code outside of your functions. list_old in func2 is pointing to a newly created copy, those two variables are different. In func3 list_old = list is assigning list_old to the original list, but then you have list = [9,9,9] which makes a new list, therefore has a new address in memory.So, list_old and list in func3 point to two different places in memory.

Here is a good post about variables in python https://medium.com/@tyastropheus/tricky-python-ii-parameter-passing-for-mutable-immutable-objects-10e968cbda35

Upvotes: 1

Related Questions