By the end of this lab, you will be able to:
Download nested.py and recursive_list.py into your
labs/lab6 folder.
Some helpful advice:
Open the file nested.py that contains a few nested list functions for you to implement. To help
you, the doctest examples illustrate (a) a base case, where no recursive calls are needed,
and (b) a general case where you combine recursive calls to return the desired result.
For each of the functions, read the docstring and implement it using recursion. Follow these four design steps:
Identify the recursive structure and write down the code template for nested lists:
def f(obj: Union[int, List]) -> ...:
if isinstance(obj, int):
...
else:
for sublist in obj:
... f(sublist) ...
Implement the base case(s) directly.
Write down a concrete example with a somewhat complex argument, and then write down the relevant recursive calls and what they should return.
Think about how to combine the recursive calls to compute the correct output.
Now, you will use your growing comfort with recursion to implement the List ADT recursively. This will be the third implementation of the List ADT that we have covered in this course. Remember that implementations can have the same public interface, even though they implement their methods quite differently! This guarantees that if client code switches to using the new implementation, it will work exactly as it did before.
Open the file recursive_list.py that contains a
partial implementation of a recursive list class RecursiveList. In this task you will implement
the rest of its methods.
There are two important things to note before you begin:
_first and _rest attributes be
None. This is expanded upon in a representation invariant in the class
documentation.When you are ready, follow these steps to learn and work with this new recursive structure.
Review the given documentation for the RecursiveList class. Carefully read the
descriptions of each attribute, and the representation invariants.
Read the docstring and code for the __init__, is_empty, and
__str__ methods and understand how each of these three methods works on these
instances.
Read the docstring for __len__ and implement the method. Your implementation should
handle the base case, where the list is empty, and the recursive case, where the list definitely has
one item, and possibly more items. Remember that even if a RecursiveList has just one
item, its _rest attribute still refers to a RecursiveList object!
Read the docstring and implementation for __contains__. Again, __contains__
has two base cases. Then read the docstring for count, which is similar to
__contains__, and implement the method.
Read the docstring for __getitem__. __getitem__ should have two base cases:
a) the list is empty, or b) the index is 0, referring to the first item in the list. Then, implement
the method.
Read the docstring for __setitem__, which is similar to __getitem__, and
implement the method.
Read the docstring for the methods insert and pop, that mutate a list at a
specified index. For each method, write down the base case(s), and then implement it using
recursion.
You may find implementing the methods _pop_first and _insert_first helpful.
If you finish the tasks above, here are some additional exercises that you may try.
In Python, functions are first-class objects, which means, among other things, that they can be passed as arguments to other functions. For example, the following function takes in two arguments, a function and an object, and tries to call the function on that object and see whether the result is True or not.
def try_function(f: Callable[[Any], bool], arg: Any) -> None:
if f(arg):
print('Success!')
else:
print('Failure...')
If we define the following function,
def positive(n: int) -> bool:
return n > 0
we can use try_function like this:
>>> try_function(positive, 10)
'Success!'
>>> try_function(positive, -4)
'Failure...'
Building on this example, implement the method map in the RecursiveList class,
which returns a new recursive list created by applying a function to each item in the original list. Note
that map does not mutate the original list.