13. References
It is important for us to have an idea of what exactly is stored in our variables
Warning
The ideas below are presented at a very high level and are not quite entirely correct for Python and other similar programming languages. The differences come up in the nuances, but the following is sufficient to cover the important ideas that you need to know. In fact, where there are differences between the following and how Python actually works is not overly important for us, especially in introductory computer science.
Note
We typically use hexadecimal (0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F) when referring to memory addresses, but for simplicity, we will use decimal numbers throughout this topic.
Here is an idealized view of memory inside a computer
13.1. Primitive Types in Memory
Let’s say we have a single integer called
xAn integer is a primitive type
In many programming languages integers take up 32 bits worth of memory
That means 32
0s and1sE.g.
00101010010010110101110100010100, which is the number709582100
Since we know how much memory an integer takes up, we can easily put integers into nicely divvied up chunks of memory
If we divided memory into blocks of 32 bits
And we create an integer variable
x = 17Something like this will happen
The value
17gets assigned to one of the 32 bit sections of memoryA label
xis created for that location
If we wanted to copy the value of
xinto another variable, I could write something likey = xWhen this happens
Copy the contents from the location with the label
xPlace the copied value into another 32 bit section of memory
Create a label
yfor the copied value’s location
The contents of
xare copied toy
This strategy works great for types that have a nicely defined sizes
But what happens when we do not know beforehand how much memory something needs in order to store it?
13.2. Lists in Memory
Above is a list with length
8The contents are labeled
a–h, but these are arbitrary labels and we can think of them as integersIn the examples so far, memory was divided into chunks of 32 bits which is perfect for integers
Unfortunately, we need to store a whole list that contains 8 integers
This needs 256 bits
Fortunately we have a solution
Store each of the elements within the list in their own memory location
Similar to how the integer
17was stored above
Section off a large block of memory for the list to hold references to each of the elements of the list
For simplicity, instead of storing references within the list, we will pretend that the contents of the list are stored within the block of memory sectioned off for the list
For example, the following image shows how we can think of storing the list
[a, b, c, d, e, f, g, h]
Just put each integer into its own memory location
Again, in reality we actually store a reference to the integers, but we are ignoring this for now
Keep track of the fact that our list starts at memory address 677 and goes to 684
The trick is in how this is managed
13.2.1. References
1z = [a, b, c, d, e, f, g, h]
Given the above list creation, the computer finds a contiguous block of memory to store the contents of the list
Each element in the list fits nicely into the divvied up sections
Then, the information needed to find and access the list contents is stored in a piece of memory labelled with the variable
zThe list is not stored in
z; the location of the list in memory is stored inz
Activity
Take a moment to look at this image and see if you can explain why we start counting at 0 when indexing lists.
If we wanted to make a copy of
zlike we did with the integersxandy, we could write something likew = zAnd just like with the integers, this copies the contents of the memory location of
zand puts it into a new location labelled with awHowever, the catch is that the contents of
zis the memory address of the listAfter making the copy into
w, how many references do have that get me to the memory location of the list?
If I want to make a change to
wand I write something likew[4] = P, the computer goes to the list referenced bywand alters the value at index4
This does not alter the contents of the memory location of
w; this alters the data at the memory location that is referenced to bywIn fact, this also alters the data at the memory location that is referenced by
zWhat would happen if I wrote
print(z[4])?
When we have two or more references referring to the same thing in memory, we call these aliases
wis an alias forzThis is discussed further in the following topic
Note
As mentioned earlier, in reality Python would not actually store the contents of the list within the block of memory allocated for the list. Instead, Python stores the contents in their own memory locations and the list stores references to the contents.
13.3. For Next Class
If you have not already, read Chapter 14 of the text
If you have not already, read Chapter 15 of the text (only lightly though)