Draw many shapes with no class explosion

Step 5 - Draw many shapes with no class explosion

The payoff: with 2 shape classes and 2 renderer classes we cover all 2 x 2 combinations without a single extra class. A naive design would need VectorCircle, RasterCircle, VectorSquare, RasterSquare and would keep growing.

Implement the helper draw_all(shapes): draw every shape already bound to some renderer and return the list of result strings in order.

Hints
Starter code
class Renderer:
    def render_circle(self, radius):
        raise NotImplementedError
    def render_square(self, side):
        raise NotImplementedError

class VectorRenderer(Renderer):
    def render_circle(self, radius):
        return "vector circle r=" + str(radius)
    def render_square(self, side):
        return "vector square s=" + str(side)

class RasterRenderer(Renderer):
    def render_circle(self, radius):
        return "raster pixels for circle r=" + str(radius)
    def render_square(self, side):
        return "raster pixels for square s=" + str(side)

class Shape:
    def __init__(self, renderer):
        self.renderer = renderer
    def set_renderer(self, renderer):
        self.renderer = renderer
    def draw(self):
        raise NotImplementedError

class Circle(Shape):
    def __init__(self, renderer, radius):
        super().__init__(renderer)
        self.radius = radius
    def draw(self):
        return self.renderer.render_circle(self.radius)

class Square(Shape):
    def __init__(self, renderer, side):
        super().__init__(renderer)
        self.side = side
    def draw(self):
        return self.renderer.render_square(self.side)

def draw_all(shapes):
    """Draw every shape in the list and return the list of result strings."""
    # TODO: return [shape.draw() for shape in shapes]
    pass
Write it on a laptop

The editor and the test runner need a wide screen. Open this page on a desktop browser and your progress will be waiting.