Explanation of list reference
Marko Rauhamaa
marko at pacujo.net
Fri Feb 14 14:56:07 EST 2014
dave em <daveandem2000 at gmail.com>:
> Case 1: Example of variable with a specific value from P 170 of IYOCGWP
>
>>>> spam = 42
>>>> cheese = spam
>>>> spam = 100
>>>> spam
> 100
>>>> cheese
> 42
>
> Case 2: Example of variable with a list reference from p 170
>
>>>> spam = [0, 1, 2, 3, 4, 5]
>>>> cheese = spam
>>>> cheese[1] = 'Hello!'
>>>> spam
> [0, 'Hello!', 2, 3, 4, 5]
>>>> cheese
> [0, 'Hello!', 2, 3, 4, 5]
>
> What I am trying to explain is this, why in case 1 when acting on spam
> (changing the value from 42 to 100) only affects spam and not cheese.
> Meanwhile, in case two acting on cheese also affects spam.
A very good question! Elementary and advanced at the same time.
There are two fundamentally different kinds of values in Python: "small"
values and "big" values. A variable can only hold a small value. A list
element can only hold a small value. A dictionary entry can only hold a
small value. The same is true for an object member (aka field).
So we have four kinds of (memory) slots: variables, list elements,
dictionary entries and fields. Any slot can only hold a small value.
The small values include numbers, booleans (True or False) and
references. All other values are big, too big to fit in a slot. They
have to be stored in a "vault" big enough to hold them. This vault is
called the heap. Big values cannot be stored in slots directly; instead,
references to big values are used.
Let me now annotate your excellent example:
spam = 42 # put the small value 42 (number) in a memory slot,
# namely a variable named "spam"
cheese = spam # copy the contents of the variable "spam" into
# another memory slot, a variable named "cheese;"
# now both variables contain the same small value 42
spam = 100 # replace the contents of the variable "spam" with the
# small value 100; leave the contents of the variable
# "cheese" intact
spam
> 100 # as expected
cheese
> 42 # ditto
spam = [0, 1, 2, 3, 4, 5]
# a list is a "big" value; the statement creates a
# list of six slots in the heap an puts a number in
# each slot; then, a reference to the list is placed
# in the variable "spam"
cheese = spam # copy the reference to the six-element list from the
# variable "spam" into the variable "cheese;" the heap
# still contains only one list, and the two variables
# refer to the same one
# (rationale: big values take time and space to copy
# in full, and almost always copying references is
# good for the problem at hand; if a full copy is
# needed, Python has ways to do that, too)
cheese[1] = 'Hello!'
# a character string (text snippet) is a "big" value;
# the statement creates the six-character string
# 'Hello!' in the heap; then, a reference to the
# string is placed in the second element of the list
# referred to by the variable "cheese"
# (that's a complicated sentence with lots to chew
# even though the Python statement looks so innocently
# simple)
# there still is a single list in the heap; the list
# is still referred to by both variables; however the
# second slot of the list, which used to hold the
# number 1, has been replaced with a reference to the
# "big" string 'Hello!'
spam
> [0, 'Hello!', 2, 3, 4, 5]
# as expected, right?
cheese
> [0, 'Hello!', 2, 3, 4, 5]
# right?
The final situation is represented by this picture of Python's memory:
spam cheese
+-----+ +-----+
| . | | . |
+--+--+ +--+--+
| |
| | VARIABLES
= = =|= = = = = = =|= = = = = = = = = = = = = = = = = = =
| / THE HEAP
| ---------
| /
| |
v v
+-----+-----+-----+-----+-----+-----+
| 0 | . | 2 | 3 | 4 | 5 | a list
+-----+--+--+-----+-----+-----+-----+
|
|
|
|
v a string
+--------+
| Hello! | a string
+--------+
Marko
More information about the Python-list
mailing list