ICS H32 Fall 2025
Exercise Set 8 Solutions


What's here?

These are solutions to a set of exercises, along with a fair amount of additional background explanation. Note that I've gone into more detail with those explanations that we would have wanted or expected students to do, but I'm using these as an opportunity to solidify your understanding; don't take this as an indication that you should be writing your answers in as much detail as I am here.


Problem 1

A solution is available at the link below.

It's based around a few ideas:


Problem 2

A complete solution is linked below, though I haven't included unit tests, mainly because there is likely to be so much variability in how students will have written them, and so many perfectly reasonable ways to write them.

As a lot of students guessed back when we wrote the original example, many of the calcs from the original example have turned into simple, one-line functions.

Two of the calcs are unlike the others, though: the "multiply by" calc and the "in calc." This is because they both represent concepts that you might normally implement as a function with multiple arguments. To make them compatible with this notion of one-argument calcs, we pass one of the arguments ahead of time, then defer the rest of the calculation until the other argument is passed at the time we actually call the calc.

(By the way, this idea of partially applying a function by passing some of its arguments, yielding a function that can be called with the rest of those arguments later, has a name in computer science: it's called currying. We had to do that by hand, but there are some programming languages — particularly those that are sometimes called functional languages, such as Haskell — that make this technique more automatic, such that calling a three-argument function with two arguments automatically returns a function that accepts only the third argument.)

So, rather than having a "multiply calc," we instead want the ability to have an object that's a "multiply-by-5 calc" or a "multiply-by-10 calc." We solved that problem originally by using classes and storing the "what we should multiply by" value in an attribute. In this version, we've instead written functions that build and return these functions on the fly, making use of the fact that we can build functions that use variables from their surrounding scope, in a similar way (and for similar reasons why) we did in the A Tkinter Application example.


Problem 3

  1. The reason why we used bound methods was because we were trying to solve a particular problem. We were writing our user interface in a class, with one object of that class representing an instance of that user interface. So, when Tkinter detected a particular event that our code was interested in, we needed it not just to call a function, but to call a method on the same object that represented our user interface. Bound methods are a way to solve that problem. If we pass a function as a parameter, that lets us call that function later; if we pass a bound method instead, that lets us say "Call this method on that object later." That distinction turned out to be vital for us, given our design.
  2. If we hadn't had bound methods at our disposal, all would not have been lost, because we could have instead defined local functions, which have access to the variables in their surrounding scope (including self), to do this job for us instead. For example, if we had wanted to call a method named _on_mouse_moved when mouse movement occurred, we could have done this:
    
    class ExampleApplication:
        ...
    
        def __init__(self):
            self._root_window = tkinter.Tk()
    
            ...
    
            def call_on_mouse_moved(event: tkinter.Event) -> None:
                self._on_mouse_moved(event)
    
            self._root_window.bind('<Motion>', call_on_mouse_moved)
    
    The idea of creating a simple, single-expression function like this is so common, Python provides a syntactic shorthand for it — though, of course, this isn't something we've seen before, so this wouldn't have been a good answer to this question, where you were limited only to things that we've seen in this course previously. A lambda expression is an expression that evaluates to a function with no name, which is allowed to contain a single expression and returns the value of that expression. For example:
    
    class ExampleApplication:
        ...
    
        def __init__(self):
            self._root_window = tkinter.Tk()
    
            ...
    
            self._root_window.bind('<Motion>', lambda event: self._on_mouse_moved(event))
    
    But even that is a lot of heavy-lifting for something that bound methods ultimately make a lot simpler, by allowing us to say this instead:
    
    class ExampleApplication:
        ...
    
        def __init__(self):
            self._root_window = tkinter.Tk()
    
            ...
    
            self._root_window.bind('<Motion>', self._on_mouse_moved)
    

Problem 4

Being that an answer to the question asked here involves discussing one's personal point of view, this problem does not have a definitive solution to share.