Homework 7: As Memory Serves

Due: Tuesday, November 21 at 11:59 pm

The late deadline for this assignment is Tuesday November 28 (after break ends). Late days will "freeze" from Wednesday to Sunday (during the break). The first counted late day will be the Monday after break (the 27th). You can have a max of two late days (the Tuesday after break) for this assignment. Note that there will be no office hours or Ed access from Wednesday 11/22 through Sunday 11/26, so plan accordingly.

Setup

  • Create two files:
    • hw7_code.py which contains your code
    • test_hw7.py which contains your tests (add import pytest at the top of this file)
  • Do not put your name anywhere in your homework files

Resources

The Assignment

The Rubber Duck family is going shopping for a new wardrobe to look snazzy in the town they just moved to. When shopping, they have to keep track of everyone's orders and the items that they are ordering. You will keep track of these orders through the memory diagrams that you will create in this homework.

image info

Learning Objectives

This assignment mostly has you working with memory diagrams, which we cover to help you understand what your code actually does when updating data. The last part gives you some practice with dictionaries, which you will need for the final project.

Learning Goals:

  • Check your understanding of how different bits of code affect the connections between data at the level of memory
  • Make sure you can write tests for functions that update data in memory
  • Practice using dictionaries

Memory Tracing (No Programming)

You can submit your answers to this one of the following ways:

  • diagrammed in a spreadsheet
  • written in a text file
  • drawn in some tool that saves to pdf
  • photograph of work done on paper

We encourage you to use a spreadsheet the way we did in class and highlight your changes!

You can use this template as a starting point. To edit it, make a copy (File -> Make a copy) and then when you are done and want to turn it in, take a screenshot and insert it into the document with your answers.

Name your file tracing.txt, tracing.pdf, or tracing.png accordingly.

Below is part of a program for managing orders in an online store. There is a data structure for the Items for sale, as well as a catalog of all items. There is a data structure for Orders, which capture the name of a customer and a list of items that the customer wants to buy. There are also two versions of a function to update the price of an item in the catalog.

At the bottom of the file is a sequence of expressions to evaluate.

Program code dropdown
from dataclasses import dataclass

@dataclass
class Item:
    descr : str
    price : float

@dataclass
class Order:
    customer : str
    items: list

# Several Items
duck_book = Item("The Fuzzy Duckling", 17.95)
cap = Item("baseball cap", 12.95)
radio = Item("radio", 10)
laptop = Item("laptop", 900)

# a catalog is a list of items
catalog = [duck_book, radio, laptop]

# Some orders
k_order = Order("Kathi", [radio, duck_book, laptop])
m_order = Order("Milda", [laptop, Item("radio", 10)])

# The companies list of open orders (that haven't been paid for yet)
open_orders = [k_order, m_order]

def update_price1(for_descr : str, new_price : float) -> None:
    """update the price for the item with the given description"""
    for item in catalog:
        if item.descr == for_descr:
            item.price = new_price


def update_price2(for_descr : str, new_price : float) -> None:
    """update the price for the item with the given description"""
    global catalog
    new_catalog = []
    for item in catalog:
        if item.descr == for_descr:
            new_catalog.append(Item(item.descr, new_price))
        else:
            new_catalog.append(item)
    # Memory point 2
    catalog = new_catalog

# The expressions to run
update_price1("radio", 8.50)
# Memory point 1
update_price2("radio", 7)
# Memory point 3
update_price1("radio", 5)
update_price1("laptop", 1100)
# Memory point 4

Task A-1: Without running the program or drawing a memory diagram, predict what will be in each of k_order, m_order, and catalog (items and their prices) after the four expressions evaluate. Write down your answers.

Note: You will not lose points for an inaccurate prediction. The point of the question is to help you calibrate your understanding of memory as you work through the problem.

Note: In the code, there is a line that says global catalog. This just means that the function is going to update the value of catalog which was defined outside the function.

Task A-2: There are four comments in the code marked "Memory point." Show the contents of memory (variables and heap) at each of these four points. Make sure to include a different memory diagram for each memory point (you should have 4 distinct diagrams).

Task A-3: Write down the contents of k_order, m_order, and catalog as if the entire code has been run, based on your work on the memory diagram.

Note: You will not lose points for an inaccurate answer for this task (as long as you appeared to take the problem seriously)

Task A-4: Now, copy and run the code and compare the final contents of k_order, m_order, and catalog to your answer to the previous task. If they differ, that is an indication that you have a mistake in your memory diagram

Hint for checking your work

We will show an example of this in class on Friday. Add a pass statement at the end of this code, and add a breakpoint (click to the left of the pass statement's line number, so that a red dot appears).

Run the debugger (Run -> Debug) and observe what the contents of k_order, m_order, and catalog are on the left side of the screen.


Task A-5: Revise your memory diagrams from Task A-2 as needed and write down your final answers for each of the four memory points.

Hint for checking your work as you go

You can add breakpoints in other parts of your code and step through to check if the values each variable takes on are the same as you put in the memory diagram at each step. Refer back to Lab 9 and the 11/17 lecture for instructions on using the debugger.


Task A-6: Reflect on your process: were your predictions correct? If yes, write down one way you approached the tasks that you feel was particularly helpful in your thinking. If no, write down a conceptual misconception (not just a wrong answer, but where you think you had a mistake in your thinking) you had and fixed.

You can write these in a text file or draw (and scan to PDF or png) pictures of memory drawn on paper. For the memory diagram, make sure the information for each memory point is clearly labeled so we see which memory layout goes with each point.

Note: Your final file should include:

  1. Your prediction from task A-1
  2. Your initial answer from task A-3
  3. Your final, revised memory diagrams from task A-5 (builds upon / corrects any mistakes from the memory diagrams from task A-2)
  4. Your reflection from task A-6

Remember to check the Handin section for more details!

Testing Under Mutation

The online store code contains the above two versions of a function called update_price. Assume we want another version of this function, update_price3, in which changes in price reflect in the catalog, but not in any orders that are still open.

Task B-1: Write, in prose (your own words), a list of the changes that you do or do not expect to see after a price is updated for different items. Put this in a comment at the top of your testing file.

Multi-line comments in Python

Python doesn't have block comments, so just use a series of comments using #.

A neat trick that you can do to comment out multiple lines at once is to select all the lines of code and then press ctrl + / or command + /!

Task B-2: Use your list to write a test function test_update_price3 (using assertions). Follow the structure of the test function that we showed in lab 10. This test method does not have to run, we will only read your test cases to check conceptual understanding of how a test should look like and would hypothetically run if you had written that function yourself and tested it. As part of this task, consider whether the data in the catalog and the open orders as set up in the starter code is sufficient, or if you need to create any new items or orders.

You are only writing a test function for this question. You are NOT writing code for update_price3 itself. The goal of this question is to see whether you are understanding how to test the behavior of a function that updates data.

Template for testing under mutation

Your function will need to set up some data (catalogs, items, and orders), make one or more calls to update_price3, then run a series of assertions to check the impacts of the update_price3 call on the data. The general form of your function should be as follows:

def test_update_price3():
    "test whether update_price3 works"
    "SETUP"
    # create data here

    "PERFORM MODIFICATIONS"
    # call update_price3

    "CHECK EFFECTS"
    # assertions go here

Dictionaries

Task C-1: In hw7_code.py, using the provided catalog list and the relevant items (duck_book, radio, laptop), create a dictionary named catalog_dict that maps the item's description to its price.

Details

This task is asking you to translate the information that appears in the catalog list into a dictionary. catalog_dict should be a dictionary whose keys are strings (the item description). The values should be a float that represents the item's price.

Task C-2: In hw7_code.py, rewrite the function update_price1 such that it updates an item's price in catalog_dict. You do not have to write tests for this function inside test_hw7.py (since your test_hw7.py file will not run after doing the Task Bs), but you should manually interact with your code to double-check that the function works. How you do this is up to you you can run the code in the terminal, you can add some more print statements to the file, or you can create a testing file that you do not turn in.

  • Call this new function new_update_price1. Do not modify update_price1.
  • new_update_price1 should take the same inputs as update_price1, and it shouldn't return anything. It should update the existing catalog_dict dictionary.
  • new_update_price1 should have the same effect as update_price1 does on items that don't exist in the catalog (we want you to reason about what happens in update_price1 in this case. How can you do something similar in new_update_price1?)

Task C-3: You now have two different implementations of catalog. One that uses lists, and another that uses a dictionary. In hw7_code.py, write a multiline comment describing the tradeoffs between both implementations, which one do you think is better? Write down your answer in a multi-line comment using #.

Handin

You will be submitting three separate files to Gradescope under Homework 7:

  • tracing.txt, tracing.pdf, or tracing.png with your answers to the "Memory Tracing" section exercises
  • test_hw7.py, which will contain the testing function from the "Testing Under Mutation" section
  • hw7_code.py with your answers to the catalog_dict dictionary and an updated version of update_price1 from the "Dictionaries" section

Theme Song

Suit & Tie by Justin Bieber ft. JAY-Z


Brown University CSCI 0111 (Fall 2023)