Exercise 3 - Variable Scope#

This is a common problem in Jupyter notebooks, where “variable scope” is not as clear as when writing a block of code. What does “variable scope” mean? In short: There are some cases where python can use variables within a function which is not declared within the function, normally if that variable is not changed. However, it is almost always better to always have any variables that a function needs be declared in the function or declared as input variables.

So to illustrate this we can do:

x = 10
def exercise3_A():
    y = x * x
    print(y)

exercise3_A()
100

But it might be much clearer to do:

x = 10
def exercise3_A(x):
    y = x * x
    return y

print(exercise3_A(x))
100

Do you understand the difference? Please ask us if it is not clear!

However, if we do:

x = 10
def exercise3_B():
    x += 1
    print(x)

exercise3_B()
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [3], in <module>
      3     x += 1
      4     print(x)
----> 6 exercise3_B()

Input In [3], in exercise3_B()
      2 def exercise3_B():
----> 3     x += 1
      4     print(x)

UnboundLocalError: local variable 'x' referenced before assignment

Then the code fails. This is because you cannot change variables within a function that are defined outside of it.

EXERCISE: Fix the code such that it correctly increments x by 1 and prints it. The value of x outside the function should also increment by 1.

# FEEL FREE TO EDIT ANY CODE IN THIS CELL TO FIX THE PROBLEM

x = 10

def exercise3_B():
    x += 1

exercise3_B()
print(x)
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [4], in <module>
      5 def exercise3_B():
      6     x += 1
----> 8 exercise3_B()
      9 print(x)

Input In [4], in exercise3_B()
      5 def exercise3_B():
----> 6     x += 1

UnboundLocalError: local variable 'x' referenced before assignment

A slightly more involved example of the following problem is this. Think about what the difference is here.

lst = [1, 2, 3]
def exercise3_C():
    lst.append(5)   # This works ok...

exercise3_C()
print(lst)

lst = [1, 2, 3]
def exercise3_D():
    lst += [5]      # ... but this fails, despite being the same operation!

exercise3_D()
print(lst)

# Again the better solution here is something like:
lst = [1, 2, 3]
def exercise3_E(lst):
    lst += [5]
    return lst

lst = exercise3_E(lst)
[1, 2, 3, 5]
---------------------------------------------------------------------------
UnboundLocalError                         Traceback (most recent call last)
Input In [5], in <module>
      9 def exercise3_D():
     10     lst += [5]      # ... but this fails, despite being the same operation!
---> 12 exercise3_D()
     13 print(lst)
     15 # Again the better solution here is something like:

Input In [5], in exercise3_D()
      9 def exercise3_D():
---> 10     lst += [5]

UnboundLocalError: local variable 'lst' referenced before assignment