Lab 7: Part 1 - Drawing Memory Diagrams
In this part of the lab, instead of working on the computer, you will practice drawing and modifying memory diagrams on a whiteboard. In each part one of you will draw the diagram and then the other person will modify it. Make sure to check your answers using the links below to reveal what the diagram should look like.
Feel free to take pictures of the whiteboard at each step if you want to retain them for your notes. Using a whiteboard is easier than using paper because you will frequently need to erase and re-draw arrows.
Memory Diagram Reminders
- Each variable gets a box. Small values, like numbers, booleans, or
None
, are written in a box. - Large values like strings or lists are written separately, with an
arrow starting in the box that points to the value.
- Each slot in a list is its own box that works the same way.
- When you see an
=
sign, follow these steps:- Identify what is on the right-hand side:
- If there's an expression on the right-hand side involving
+
,*
, or another operator or function call, the result depends on the operation performed, and will usually be a newly-created object. - If the right-hand side just has a variable reference (possibly with indexing involved), then the result will be a copy of whatever is in the box that the right-hand expression identifies.
- If there's an expression on the right-hand side involving
- Identify which box is being updated based on the left-hand side.
- If it's a variable, update that box.
- If it involves indexing, figure out which box of which list is being updated.
- Take the expression result and replace the contents of the box being updated with that value. Do not create any new arrows at this point unless the result you are using is an arrow (in that case, the new arrow points to the same place as the one you're copying).
- Identify what is on the right-hand side:
- Besides assignment using
=
, Specific methods likeappend
,insert
, andpop
can change the contents of the object they apply to.+=
and related updating-assignments also change the value on their left-hand side. - Arrows cannot point to slots within lists. They can only point to strings or entire lists.
Simple variable diagrams
1. Basic Values
On a whiteboard, draw a memory diagram for the state at the end of this code:
num = 10
word = 'hello'
Check your answer
Modify your partner's diagram to update it based on the following additional assignments:
word = 10
value = num * word
Check your answer
2. Duplicates
Draw the memory diagram for the the end of this code:
a = 10
b = 10
c = 'hello'
d = 'hello'
Check your answer
Note that it would also be valid to draw a second arrow in box 'd' that points to the same 'hello' you drew for 'c'. Becuase strings are immutable, it doesn't matter to the programmer whether they are aliases or clones, and Python often creates aliases instead of clones when it can.
Modify your partner's diagram to update it based on the following additional assignments:
b = d
c = a
Check your answer
Note that it's also valid to draw a second arrow and 'hello' for 'b', but that's more work than just drawing an arrow to the 'hello' you already drew.
3. Swap
Draw the memory diagram for the the end of this code:
x = 'A'
y = x + 'B'
Check your answer
Note that it's not valid to draw any arrows between x and y or between their values.
Now modify that based on these lines of code (Reminder: code executes one line at a time, using whatever variable values have been defined up to that point):
x = y
y = x
Check your answer
Note that when we assign 'x = y', the old value of x is thrown away, since no other variables reference it.
Now modify the diagram based on these addiional lines of code:
x += 'C'
tmp = x
x = y
y = tmp
Check your answer
Here we used a third variable to help facilitate swapping x and y. Note
that you don't have to draw the arrows crossed like this, but if you
update things one-by-one, your arrows may end up this way unless you
re-draw the strings 'ABC' and 'AB'. Putting 'ABC' below 'AB' avoids
having to cross any arrows. The final value of x
here is 'AB'
and the
final value of y
(and also of tmp
) is 'ABC'
.
Diagrams for Lists
4. List Basics
Draw a memory diagram for the end of these lines of code:
x = [11, 22]
y = x
z = list(x) # creates a clone
Check your answer
Now modify that diagram based on the following additional code that uses indexing and slicing:
x0 = x[0]
y1 = y[1]
zs = z[0:1]
Check your answer
Note that slicing creates a new list, and that indexing does NOT create new references when the items at the indices used are numbers. (If the thing in a slot being indexed slot is a reference, you'll get a copy of that reference).
Now add this variable to your diagram:
all = [x, y, z]
Check your answer
5. List Mutation
Draw a memory diagram for the end of these lines of code:
nums = [7, 23, 51]
alias = nums
clone = nums[:] # slice from start to end
Check your answer
Now modify that diagram based on the following additional code:
ext = clone + [96]
alias.append(121)
Check your answer
Next draw the diagram after these additional lines:
p = nums.pop(1)
clone.insert(0, 3)
nl = len(nums)
al = len(alias)
cl = len(clone)
el = len(ext)
Check your answer
Finally modify the diagram to account for this line (note: part of this line of code does NOT make sense):
alias = alias.append(239)
Check your answer
Note that append
modifies the list you apply it to, but its result
value is None
. You should never write variable = variable.append(...)
because this will replace the variable's value with
None
, which isn't useful. Just write variable.append(...)
on its own
instead, as we did in the second step for this example.
Note also that the number does in fact get appended to the list in
question, which we can still see because alias
was an alias of nums
.
Also note that the length of the nums list is now 4, and alias
isn't a
list any more, but the nl
and al
variables don't get updated: they
hold the old length values computed previously.
6. List Mutation 2
Write the memory diagram for the end of this code:
x = [80, 75, 50]
y = x
z = [x, y[1]]
Check your answer
Now modify that to reflect the state after these two lines have been run:
x[0] = 100
y.append('hi')
Check your answer
Finally show what memory looks like after these two additional lines:
z.insert(1, x[1] + y[1])
removed = z[0].pop(1)
Check your answer
7. Mutation in a Loop
Draw the memory diagram for the end of this code:
s = []
t = []
for i in range(3, 25, 7):
s.append(i)
Check your answer
Note that since t
remains empty, it ends up as an empty box without any
slots in it.
Now draw the memory diagram after these additional lines of code have run:
for i in range(3):
t.append(s[i])
Check your answer
This code copies the first three entries of s
into t
. Note how re-using i
as the loop variable changes its value. Although not shown here, i
changes
value in every iteration of the loop.
Next, draw the memory diagram after these additional lines of code have run (note: these lines of code don't make a lot of sense):
for x in s:
x += 1
Check your answer
Note that values in s
are unchanged: the loop copies those values into x
,
and then changes x
. This code doesn't make sense because x
gets overwritten
in every iteration, and nothing else is changed. We could have just said x = s[-1] + 1
to set x
equal to one more than the last element in s
.
Next, draw the memory diagram after these additional lines of code have run (note: these lines of code make more sense than the ones above):
for i in range(len(s)):
s[i] += 1
Check your answer
Here we actually modify the values in s
within the loop, adding 1 to each
value. That's because we're using indexing directly to set values within the
loop.
Note that i
also changes since we used it as our loop variable.
Finally, draw the memory diagram after these lines:
u = []
for x in t:
u.insert(0, x)
Check your answer
This code copies t
in reverse order, since each new item it sees is farther
along in t
but is being added to the beginning of u
. Note that x
also
gets overwritten.
Whew! Done with drawing memory diagrams. Now move onto the next part of the lab where you'll get practice writing code involving memory diagrams.