Exercises#
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}")
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)
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#
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 argumentx
causesx
to become an alias ofglobals
, i.e., another reference to the same list. Settingx[1]
to"Venus"
modifies the second element of that list, which is still the list thatglobals
is bound to.The assignment to
galactics
within the function creates a new local variable calledgalactics
, distinct from the global variable calledgalactics
. It therefore has no effect outside the function.We passed
locals
as argumenty
, soy
is initially an alias tolocals
within the function. When we assignz
the value ofy
, we have three names (locals
,y
, andz
) for the same list. But then we change the local (withinmess
) binding ofy
to a new list["Corvallis", "Salem"]
. This has no effect on the bindings oflocals
orz
.We return
z
, which is bound to the same list aslocals
.towns
then becomes an alias forlocals
.
When mess
begins execution, bindings look like this:
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:
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
.
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!
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.