# Question 1

Implement a class LoopList that has a method at_index. If at_index is called with an index that is too large, the LoopList will loop around back to the beginning.

class LoopList(object):
"""
>>> x = LoopList([3, 1, 4])
>>> [x.at_index(i) for i in range(10)]  # loops around!
[3, 1, 4, 3, 1, 4, 3, 1, 4, 3]
"""
pass


Toggle Solution

class LoopList(object):
"""
>>> x = LoopList([3, 1, 4])
>>> [x.at_index(i) for i in range(10)]  # loops around!
[3, 1, 4, 3, 1, 4, 3, 1, 4, 3]
"""
def __init__(self, lst):
self.lst = lst

def at_index(self, idx):
return self.lst[idx % len(self.lst)]


# Question 2

Draw the environment diagram (this one’s hard!).

def campa(nile):
def ding(ding):
nonlocal nile
def nile(ring):
return ding
return nile(ding(1914)) + nile(1917)

ring = campa(lambda nile: 100)


Toggle Solution

When looking through the environment diagram, be very very careful about the order of operations! Remember that for every function call, we do:

1. Evaluate the operator (this means resolving the name of the function to the function itself!)
2. Evaluate the operands, from left to right.
3. Apply the operator on the operands.