Exercises

Exercises#

  1. Predict the output of this program without executing it. It is a good idea to draw diagrams and/or tables rather than trying to do this in your head.

globals = ["Jupiter", "Mars"]
galactics = ["Andromeda", "Milky Way"]
locals = ["Portland", "Medford"]

def mess(x: list[str], y: list[str]) -> list[str]:
    """Gonna mess with your data!"""
    x[1] = "Venus"
    galactics = ["Triangulum", "Pinwheel" ]
    z = y
    y = ["Corvallis", "Salem"]
    return z

towns = mess(globals, locals)
print(f"Globals is {globals}")
print(f"Galactics is {galactics}")
print(f"Locals is {locals}")
print(f"Returned {towns}")
  1. Predict what this program prints without executing it.

countdown = []

def launch(n: int):
    countdown.append(n)
    if n > 0:
        launch(n-1)
    else:
        print(countdown)
        print("Blast off!")

launch(5)
  1. This program will not work. What error do you expect?

countdown = []
n = 10

def launch():
    countdown.append(n)
    if n > 0:
        n = n - 1
        launch()
    else:
        print(countdown)
        print("Blast off!")

launch()

Solutions to exercises#

  1. Predict the outcome of this program without executing it.

globals = ["Jupiter", "Mars"]
galactics = ["Andromeda", "Milky Way"]
locals = ["Portland", "Medford"]

def mess(x: list[str], y: list[str]) -> list[str]:
    """Gonna mess with your data!"""
    x[1] = "Venus"
    galactics = ["Triangulum", "Pinwheel" ]
    z = y
    y = ["Corvallis", "Salem"]
    return z

towns = mess(globals, locals)
print(f"Globals is {globals}")
print(f"Galactics is {galactics}")
print(f"Locals is {locals}")
print(f"Returned {towns}")
Globals is ['Jupiter', 'Venus']
Galactics is ['Andromeda', 'Milky Way']
Locals is ['Portland', 'Medford']
Returned ['Portland', 'Medford']

Do any of those surprise you?

  • Passing globals as argument x causes x to become an alias of globals, i.e., another reference to the same list. Setting x[1] to "Venus" modifies the second element of that list, which is still the list that globals is bound to.

  • The assignment to galactics within the function creates a new local variable called galactics, distinct from the global variable called galactics. It therefore has no effect outside the function.

  • We passed locals as argument y, so y is initially an alias to locals within the function. When we assign z the value of y, we have three names (locals, y, and z) for the same list. But then we change the local (within mess) binding of y to a new list ["Corvallis", "Salem"]. This has no effect on the bindings of locals or z.

  • We return z, which is bound to the same list as locals. towns then becomes an alias for locals.

When mess begins execution, bindings look like this:

Bindings at entry to ; x and y are aliases to globals and locals

The local variables x and y are references that have been copied from globals and locals, respectively. When mess is just about to return, bindings look like this:

Bindings at exit from ;   and  are local variables

Only globals has been changed in the global namespace.
galactics is unchanged in the global namespace because the new assignment to galactics was to a local variable in the scope of function mess.

  1. Predict what this program prints without executing it.

countdown = []

def launch(n: int):
    countdown.append(n)
    if n > 0:
        launch(n-1)
    else:
        print(countdown)
        print("Blast off!")

launch(5)
[5, 4, 3, 2, 1, 0]
Blast off!
  1. This program will not work. What error do you expect?

countdown = []
n = 10

def launch():
    countdown.append(n)
    if n > 0:
        n = n - 1
        launch()
    else:
        print(countdown)
        print("Blast off!")

launch()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [3], in <cell line: 0>()
     10         print(countdown)
     11         print("Blast off!")
---> 13 launch()

Input In [3], in launch()
      4 def launch():
----> 5     countdown.append(n)
      6     if n > 0:
      7         n = n - 1

UnboundLocalError: cannot access local variable 'n' where it is not associated with a value

Because of the assignment n = n - 1, n will be a local variable in the scope of launch. But n is referenced in the call to append and also in the if statement, before it has been given a value. These references will break (exception UnboundLocalError) even though there is another variable n in the global scope.