0

I would like to know why a is not changed in the code below, but f is changed.

After assigning 5 to c[0], a remains 2 and c[0] changes from 2 to 5. This makes sense to me because I did not assign a value to a. After assigning 8 to t[0][0], f[0] is changed from 1 to 8. This does not make sense to me, because I am changing t not f.

a = 2
b = 3
c = [a,b]

print(c)
print(a)

c[0]= 5

print(c)
print(a)


f = [1,1,1]
s = [2,2,2]
t = [f,s]

print(t)
print(f)

t[0][0] = 8

print(t)
print(f)

output:

[2, 3]
2
[5, 3]
2
[[1, 1, 1], [2, 2, 2]]
[1, 1, 1]
[[8, 1, 1], [2, 2, 2]]
[8, 1, 1]

EITB
  • 71
  • 1
  • 5
  • Because you **never mutated the int** inside the list (indeed, int objects are immutable so there is no direct way to do that unless you are willing to hack the runtime internals) and in the other case, you **do** mutate the list inside the list. Read: https://nedbatchelder.com/text/names.html – juanpa.arrivillaga Dec 23 '20 at 04:29
  • You'll see the same thing if you do `t[0] = [8, 1, 1]`. – juanpa.arrivillaga Dec 23 '20 at 04:30
  • "This does not make sense to me, because I am changing t not f." No, you are **not changing `t`**. You are changing an object that `t` contains, which happens to be referenced by `f`, so you have it backwards – juanpa.arrivillaga Dec 23 '20 at 04:32
  • 1
    watch this video by ned bachelder and you'll understand all of this. https://youtu.be/_AEJHKGk9ns (start at 3:40 or so if you're impatient) – acushner Dec 23 '20 at 04:33
  • This is your question. There are many like it, but this one is yours. Probably still a good idea to look at the others though, because it's all the same problem: `t` is referring to `f` and `s`, not a copy of them. https://stackoverflow.com/questions/60326624/unexpected-change-of-list-value – Grismar Dec 23 '20 at 04:39
  • This might help: http://pythontutor.com/ – deceze Dec 23 '20 at 06:13
  • The video by acushner cleared things up. I now understand the difference between mutable and immutable objects in python. After reading the responses, I learned about the difference. Thanks – EITB Dec 24 '20 at 05:14

2 Answers2

0

What is happening here is that lists are treated by reference in python, what this means is that when you write this:

f = [1,1,1]
s = [2,2,2]
t = [f,s]

t[0] is pointing to the list f and f[0] is pointing to the value 1 in other words when you change t[0][0] = 8 in someway you are saying f[0] = 8.

Below is how it should look the memory before and after the assignation of t[0][0] = 8

image of how should lool the memory1

r4cc00n
  • 1,927
  • 1
  • 8
  • 24
0

Python has a default aliasing property with assigning objects. we can verify this using "is" operator.

is "a" and "b" are two different list "is" operation will return a False.

a = [1,2,3]
b = [1,2,3]
print(a)
[1, 2, 3]
print(b)
[1, 2, 3]
print(a==b)
True
print(a is b)
False

if "a" is assigned to "c" , on doing "is" operation will receive a True. means both objects are same, or poiting to same memory.

assign a to c

c = a
print(a == c)
True
print(a is c)
True

a and c are pointing to same object, changes on one list will get updated on other object also

a[0]=5
print(a)
[5, 2, 3]
print(c)
[5, 2, 3]

we can do a explicit copy or cloning of existing list.

cloning using slicing

d=a[:]
print(a==d)
True
print(a is d)
False

d[0] = 6
print(d)
[6, 2, 3]
print(a)
[5, 2, 3]

Please try below code.

f = [1,1,1]
s = [2,2,2]
t = [f[:],s[:]]
print(t)
[[1, 1, 1], [2, 2, 2]]
t[0][0] = 8
print(t)
[[8, 1, 1], [2, 2, 2]]
print(f)
[1, 1, 1]
Nishad C M
  • 142
  • 6
  • 1
    “Default aliasing for memory optimization” is an… odd way of describing it. You’re simply assigning yet another name to the object. There’s only one object until and unless you explicitly copy it. Not because memory, but because you explicitly created only one object and never copied it. – deceze Dec 23 '20 at 06:17
  • thanks, updated content – Nishad C M Dec 23 '20 at 15:47