Wednesday, July 6, 2022

[FIXED] What determines if the variable will be altered or not?

Issue

class MyClass:
    def __init__(self, a):
        self.a = a

def append(some_list):
    some_list.append(["d"])
    
foo =[["a"],["b"],["c"]]
bar = foo
my_class = MyClass(foo)

append(bar)

for item in bar:
    item[0] += "x"
    letters = item[0]
    letters += "z"
print (my_class.a)

Yields the output

[['ax'], ['bx'], ['cx'], ['dx']]

There’s quite a bit going on in the example and I feel pretty good about all of it except for I’d expect “z” to be tagged onto the strings as well but it’s not.

Can someone explain why it makes sense “z” is not included on the strings?

I thought that the indexing would return “the container” with the string and then appending the “z” would alter the stored string. Apparently a distinct “container” is made but I don’t understand how or why.

(If appending to the string makes a new string, I don’t know why the same behavior would happen with integers as well which I tested... Would using floats have a different result?)


Solution

It is because of mutable object. For example

>>>l1 = [1,2,3]
>>>l2 = l1
>>>l2[0]=4
>>>print(l1[0])
4

In the example, l1 and l2 points to the same memory location. To create l1 as a copy of l2, use copy():

>>>l1 = [1,2,3]
>>>l2 = l1.copy()
>>>l2[0]=4
>>>print(l1[0]) 
1
>>>print(l2[0])
4

EDIT: change explanation as a comment suggested.

In your example, foo and bar point to the same memory location: what you changes in foo also changes in bar. Why it does not append "z" is because letters is a declared variable that has the value of item[0], but it is not mutating. If you print(letters) it will print "dz".



Answered By - Minh-Long Luu
Answer Checked By - Clifford M. (PHPFixing Volunteer)

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.