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

Simple variable diagrams

1. Basic Values

Partner A

On a whiteboard, draw a memory diagram for the state at the end of this code:

num = 10
word = 'hello'
Check your answer

A memory diagram corresponding to the following memory report: um = 10; word = @1; @1: 'hello'

Partner B

Modify your partner's diagram to update it based on the following additional assignments:

word = 10
value = num * word
Check your answer

A memory diagram corresponding to the following memory report: num = 10; word = 10; value = 100

2. Duplicates

Partner B

Draw the memory diagram for the the end of this code:

a = 10
b = 10
c = 'hello'
d = 'hello'
Check your answer

A memory diagram corresponding to the following memory report: a = 10; b = 10; c = @1; d = @2; @1: 'hello'; @2: 'hello' Note: It would also be valid to use @1  for both c and d.

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.

Partner A

Modify your partner's diagram to update it based on the following additional assignments:

b = d
c = a
Check your answer

A memory diagram corresponding to the following memory report: a = 10; b = @2; c = 10; d = @2; @2: 'hello'

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

Partner A

Draw the memory diagram for the the end of this code:

x = 'A'
y = x + 'B'
Check your answer

A memory diagram corresponding to the following memory report: x = @1; y = @2; @1: 'A'; @2: 'AB'

Note that it's not valid to draw any arrows between x and y or between their values.

Partner B

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

A memory diagram corresponding to the following memory report: x = @2; y = @2; @2: 'AB'

Note that when we assign 'x = y', the old value of x is thrown away, since no other variables reference it.

Partner A

Now modify the diagram based on these addiional lines of code:

x += 'C'

tmp = x
x = y
y = tmp
Check your answer

A memory diagram corresponding to the following memory report: x = @1; y = @2; tmp = @1; @1: 'ABC'; @2: 'AB'

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

Partner B

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

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; @1: [11, 22]; @2: [11, 22]

Partner A

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

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; @1: [11, 22]; @2: [11, 22]; x0 = 11; y1 = 22; zs = @3; @3: [11]

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).

Partner B

Now add this variable to your diagram:

all = [x, y, z]
Check your answer

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; @1: [11, 22]; @2: [11, 22]; x0 = 11; y1 = 22; zs = @3; all = @4; @3: [11]; @4: [@1, @1, @2]

5. List Mutation

Partner A

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

A memory diagram corresponding to the following memory report: nums = @1; alias = @1; clone = @2; @1: [7, 23, 51]; @2: [7, 23, 51]

Partner B

Now modify that diagram based on the following additional code:

ext = clone + [96]
alias.append(121)
Check your answer

A memory diagram corresponding to the following memory report: nums = @1; alias = @1; clone = @2; ext = @3; @1: [7, 23, 51, 121]; @2: [7, 23, 51]; @3: [7, 23, 51, 96]

Partner A

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

A memory diagram corresponding to the following memory report: nums = @1; alias = @1; clone = @2; ext = @3; @1: [7, 51, 121]; @2: [3, 7, 23, 51]; @3: [7, 23, 51, 96]; p = 23; nl = 3; al = 3; cl = 4; el = 4

Partner B

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

A memory diagram corresponding to the following memory report: nums = @1; alias = None; clone = @2; ext = @3; @1: [7, 23, 51, 121, 239]; @2: [7, 23, 51]; @3: [7, 23, 51, 96]

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

Partner A

Write the memory diagram for the end of this code:

x = [80, 75, 50]
y = x
z = [x, y[1]]
Check your answer

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; @1: [80, 75, 50]; @2: [@1, 75]

Partner B

Now modify that to reflect the state after these two lines have been run:

x[0] = 100
y.append('hi')
Check your answer

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; @1: [100, 75, 50, @3]; @2: [@1, 75]; @3: 'hi'

Partner A

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

A memory diagram corresponding to the following memory report: x = @1; y = @1; z = @2; removed = 75; @1: [100, 50, @3]; @2: [@1, 150, 75]; @3: 'hi'

7. Mutation in a Loop

Partner B

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

A memory diagram corresponding to the following memory report: s = @1; t = @2; i = 17; @1: [3, 10, 17, 24]; @2: []

Note that since t remains empty, it ends up as an empty box without any slots in it.

Partner A

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

A memory diagram corresponding to the following memory report: s = @1; t = @2; i = 2; @1: [3, 10, 17, 24]; @2: [3, 10, 17]

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.

Partner B

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

A memory diagram corresponding to the following memory report: s = @1; t = @2; i = 2; x = 25; @1: [3, 10, 17, 24]; @2: [3, 10, 17]

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.

Partner A

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

A memory diagram corresponding to the following memory report: s = @1; t = @2; i = 3; x = 25; @1: [4, 11, 18, 25]; @2: [3, 10, 17]

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.

Partner B

Finally, draw the memory diagram after these lines:

u = []
for x in t:
    u.insert(0, x)
Check your answer

A memory diagram corresponding to the following memory report: s = @1; t = @2; i = 3; x = 17; u = @3; @1: [4, 11, 18, 25]; @2: [3, 10, 17]; @3: [17, 10, 3]

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.

Table of Contents