Homework 10: Iterators and Generators

Due by 11:59pm on Wednesday, November 19

Instructions

Download hw10.zip. Inside the archive, you will find a file called hw10.py, along with a copy of the ok autograder.

Submission: When you are done, submit the assignment to Gradescope. You may submit more than once before the deadline; only the final submission will be scored. Check that you have successfully submitted your code on Gradescope. See Lab 0 for more instructions on submitting assignments.

Using Ok: If you have any questions about using Ok, please refer to this guide.

Readings: You might find the following references useful:

Grading: Homework is graded based on correctness. Each incorrect problem will decrease the total score by one point. This homework is out of 6 points.

Required Questions

Iterators and Generators

Q1: Scale

Implement an iterator class called ScaleIterator that scales(multiplies) elements in an iterable s by a number k.

Be careful! If your __next__ method never raises StopIteration, you might loop forever.

class ScaleIterator:
    """An iterator the scales elements of the iterable s by a number k.

    >>> s = ScaleIterator([1, 5, 2], 5)
    >>> for elem in s:
    ...     print(elem)
    5
    25
    10
    >>> m = ScaleIterator([1, 2, 3, 4, 5, 6], 2)
    >>> [next(m) for _ in range(5)]
    [2, 4, 6, 8, 10]
    """
    def __init__(self, s, k):
        "*** YOUR CODE HERE ***"

    def __iter__(self):
        return self

    def __next__(self):
        "*** YOUR CODE HERE ***"

Use Ok to test your code:

python3 ok -q ScaleIterator

Q2: Amplify

Implement amplify, a generator function that takes a one-argument function f and a starting value x. The element at index k that it yields (starting at 0) is the result of applying f k times to x. It terminates whenever the next value it would yield is a falsy value, such as 0, "", [], False, etc.

def amplify(f, x):
    """Yield the values x, f(x), f(f(x)), ... that are all truthy values
    and stop yielding once the sequence reaches the first falsy value.

    >>> gen1 = amplify(lambda s: s[1:], 'boxes')
    >>> [next(gen1) for _ in range(5)]
    ['boxes', 'oxes', 'xes', 'es', 's']
    >>> try:
    ...     next(gen1)
    ... except StopIteration:
    ...     print('Correctly raised StopIteration')
    ... else:
    ...     print('Expected StopIteration error but was not raised')
    Correctly raised StopIteration
    >>> gen2 = amplify(lambda x: x // 2 - 1, 14)
    >>> [next(gen2) for _ in range(3)]
    [14, 6, 2]
    >>> try:
    ...     next(gen2)
    ... except StopIteration:
    ...     print('Correctly raised StopIteration')
    ... else:
    ...     print('Expected StopIteration error but was not raised')
    Correctly raised StopIteration
    """
    "*** YOUR CODE HERE ***"

Use Ok to test your code:

python3 ok -q amplify

Q3: Countdown

Write both a generator function and an iterator (that is not a generator) that count down to 0.

def countdown(n):
    """
    A generator that counts down from N to 0.
    >>> for number in countdown(5):
    ...     print(number)
    ...
    5
    4
    3
    2
    1
    0
    >>> for number in countdown(2):
    ...     print(number)
    ...
    2
    1
    0
    """
    "*** YOUR CODE HERE ***"
class Countdown:
    """
    An iterator that counts down from N to 0.
    >>> for number in Countdown(5):
    ...     print(number)
    ...
    5
    4
    3
    2
    1
    0
    >>> for number in Countdown(2):
    ...     print(number)
    ...
    2
    1
    0
    """
    def __init__(self, cur):
        self.cur = cur

    def __next__(self):
        "*** YOUR CODE HERE ***"

    def __iter__(self):
        """So that we can use this iterator as an iterable."""
        return self

Use Ok to test your code:

python3 ok -q countdown
python3 ok -q Countdown

Submit Assignment

Submit this assignment by uploading any files you've edited to the appropriate Gradescope assignment. Lab 00 has detailed instructions.