Problem 421102 · easy · Level 04 Non-Linear Data Structures

A Family of Shapes

py-inheritance · abstract base classes · super · geometry

A drawing program's shapes all report their area and perimeter in the same format, and they can be compared by size. Write a small family of classes:

  • Shape, the base class. It cannot be created on its own: Shape() raises TypeError. Every shape has area() and perimeter(), and the base class provides, for every shape:
    • describe(), returning "<ClassName>: area <a>, perimeter <p>" with both numbers to 2 decimals, where <ClassName> is the name of the object's own class;
    • bigger_than(other), which is True when this shape's area is larger than other's.
  • Rectangle(width, height), with attributes width and height.
  • Square(side), which is a rectangle (isinstance(Square(2), Rectangle) is True) whose width and height both equal side.
  • Circle(radius).
  • Triangle(a, b, c) from its three side lengths; if the sides cannot make a triangle (one side is at least the sum of the other two), it raises ValueError.

The tests also build shapes of their own, as subclasses of your Shape, with the helper custom_shape(name, area, perimeter); describe() and bigger_than() must work for them unchanged. The helper raises(fn, *args) returns the name of the exception a call raises, or None.

Examples

Input:  [s.describe() for s in [Rectangle(3, 4), Square(2), Circle(1)]]
Output: ['Rectangle: area 12.00, perimeter 14.00',
         'Square: area 4.00, perimeter 8.00',
         'Circle: area 3.14, perimeter 6.28']

Input:  Triangle(3, 4, 5).bigger_than(Square(2)), raises(Shape), raises(Triangle, 1, 2, 3)
Output: (True, 'TypeError', 'ValueError')

Constraints

  • All lengths are positive numbers up to 10**4.
  • Use math.pi for circles.

Goals

  • Put behaviour shared by every shape in one base class
  • Override only what differs in each subclass, and extend `__init__` with `super()`
  • Make a base class that cannot be used on its own
Starting Python…