Tutorial A9 – Solutions

1 Write a set of functions that can be used to maintain a shopping-list saved to a file on disk. We want to represent the shopping list in memory as a dictionary with items to buy as keys and quantities as values. On disk we need a text file with two columns (items, quantity). In the first line, add a comment explaining the content (starting with a #). We need the following functions (names are of course free to change):

  • read: the function should read a file from disk in the expected format and return a shopping-list dictionary. The function needs to handle the situation in which no file is found to read from.

[1]:
def read(f):
    """Read a shopping list

    Args:
        f: Shopping-list file on disk

    Returns:
        Shopping-list dictionary
    """

    d = {}

    try:
        with open(f) as f_:
            for c, line in enumerate(f_):
                if line.startswith("#"):
                    continue
                try:
                    item, q = line.split()
                    d[item] = int(q)

                except (IndexError, ValueError):
                    print("Parsing error on line {c}")

    except FileNotFoundError:
        print("No existing shopping-list found. Creating a new one.")

    return d
  • write: the function should get a dictionary and write the current state of the shopping-list to disk.

[2]:
def write(d, f):
    """Write a shopping list

    Args:
        d: Shopping-list dictionary
        f: Shopping-list file on disk

    Returns:
        None
    """

    with open(f, "w") as f_:
        f_.write("# Shopping-list\n")
        f_.write("# By this item; In this amount\n")
        for k, v in d.items():
            f_.write(f"{k}    {v}\n")
  • add_item: the function should get a new item we need to buy (string) and a quantity (integer; let’s neglect units here for the sake of simplicity). The item should be added to our dictionary and the file on disk should be updated automatically. The function needs to know the current state of the shopping-list (the location of the file on disk). Advanced If an item we want to add to the list is already in there, add the quantities.

[3]:
def add_item(item, quantity=1, f=None):
    """Add item to shopping list

    Args:
        d: Shopping-list dictionary
        item (str): What to buy?
        qunatity (int): How much to buy?
        f: Shopping-list file on disk

    Returns:
        Updated dictionary
    """

    if not f:
        f = "io/shopping_list.dat"

    d = read(f)

    if item in d:
        d[item] += quantity
    else:
        d[item] = quantity

    write(d, f)

    return d
  • Advanced cross_off_item: the function should get an item we have bought and a quantity. Subtract the quantity from the corresponding item in the list. Remove the item completely, if we have bought enough. Print a message, if the item was not in the list in the first place.

[4]:
def cross_off_item(item, quantity=1, f=None):
    """Add item to shopping list

    Args:
        d: Shopping-list dictionary
        item (str): What have you bought?
        qunatity (int): How much?
        f: Shopping-list file on disk

    Returns:
        Updated dictionary
    """

    if not f:
        f = "io/shopping_list.dat"

    d = read(f)

    if item in d:
        d[item] -= quantity
        if d[item] < 1:
            del d[item]
    else:
        print("Bought item was not on your list.")

    write(d, f)

    return d
  • Advanced pretty_print: the function should display the content of the shopping-list dictionary in a nicer format. Print for each item the quantities after a newline and indented by four spaces.

[5]:
def pretty_print(d):
    for k, v in d.items():
        print(f"{k}:\n    {v}\n")
  • Demonstrate your functions in action.

[6]:
# Add our first item
d = add_item("Milk")
pretty_print(d)
No existing shopping-list found. Creating a new one.
Milk:
    1

[7]:
# And another one
d = add_item("Sugar")
pretty_print(d)
Milk:
    1

Sugar:
    1

[8]:
# Actually I will need more milk
d = add_item("Milk")
pretty_print(d)
Milk:
    2

Sugar:
    1

[9]:
# Show how the file looks like
with open("io/shopping_list.dat") as f_:
    for line in f_:
        print(line.strip())
# Shopping-list
# By this item; In this amount
Milk    2
Sugar    1
[10]:
# Went shopping and bought ...
d = cross_off_item("Milk", quantity=3)
pretty_print(d)
Sugar:
    1

[11]:
# ... and ...
d = cross_off_item("Beer", quantity=6)
pretty_print(d)
Bought item was not on your list.
Sugar:
    1