Home > Blockchain >  I'm trying to understand how reference works in python
I'm trying to understand how reference works in python

Time:03-06

After line 7, I haven't written a single line of code which mentions the list named 'outer'. However, if you execute it, you'll see that the 'outer' (i.e, the nested lists inside it) list would change/update due to lines 10 and 12...

I'm guessing it has something to do with reference vs value. My question is, why didn't line 13 effect (change/update) the 'outer' list the same way that lines 7 and 10 did? I'm trying to undertand this concept. How do I go about it. I know there's a lot of resources online.. but I don't even know what to google. Please help.

inner = []
outer = []

lis = ['a', 'b', 'c']

inner.append(lis[0])
outer.append(inner) <<---- Line 7 <<

print(outer)
inner.append(lis[1]) <<---- Line 10 <<
print(outer)
inner.append(lis[2]) <<---- Line 12 <<
print(outer)
lis[2] = 'x' <<---- Line *******13******* <<
print(outer)

CodePudding user response:

This is a boiled-down version of your example:

some_list = []
a = 2

some_list.append(a)
a = 3

print(some_list)  # output: [2]
print(a)  # output: 3

If we follow your original logic, you would expect some_list to contain the value 3 when we print it. But the reality is that we never appended a itself to the list. Instead, writing some_list.append(a) means appending the value referenced by a to the list some_list.

Remember, variables are simply references to a value. Here's the same snippet as above, but with an explanation of what's referencing what.

some_list = []  # the name "some_list" REFERENCES an empty list
a = 2  # the name "a" REFERENCES the integer value 2

some_list.append(a)  # we append the value REFERENCED BY "a" 
                     # (the integer 2) to the list REFERENCED 
                     # BY "some_list". That list is not empty
                     # anymore, holding the value [2]

a = 3  # the name "a" now REFERENCES the integer value 3. This
       # has no implications on the list REFERENCED BY "some_list".
       # We simply move the "arrow" that pointed the name "a" to
       # the value 2 to its new value of 3

print(some_list)  # output: [2]
print(a)  # output: 3

The key aspect to understand here is that variables are simply references to a value. Writing some_list.append(a) does not mean "place the variable a into the list" but rather "place the value that the variable a references at this moment in time into the list". Variables cannot keep track of other variables, only the values that they are a reference to.

This becomes even clearer if we append to some_list a second time, after modifying the value that a references:

some_list = []
a = 2

some_list.append(a)
a = 3
some_list.append(a)

print(some_list)  # output: [2, 3]
print(a)  # output: 3

CodePudding user response:

In Python, when you store a list in variable you don't store the list itself, but a reference to a list somewhere in the computer's RAM. If you say

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

then both a and b will be references to the same list as you set b to a, which is a reference to a list. Then, modifying a will modify b and vice-versa. c, however, is an integer; it's not referenced. It's like that:

  ┌───┐
a │ █━┿━━━━━━━━━━━━━━━┓ ┌───┬───┬───┐
  └───┘               ┠→│ 0 │ 1 │ 2 │
  ┌───┐               ┃ └───┴───┴───┘
b │ █━┿━━━━━━━━━━━━━━━┛
  └───┘
  ┌───┐
c │ 3 │
  └───┘

a and b are references to a same list, but c is an integer and is the value itself and not a reference to it.

So, let's go back to your program. When you say inner.append(lis[n]) you add the value at the end of the list inner. You don't add the reference to the item #2 of the list lis but you add the value itself! If you modify lis, then it will have an impct only on variables that are references to lis.

If you want inner to be modified if you modify lis, then replace the inner.append(lis[n])s by inner.append(lis).

  • Related