Problem A
Shapes
The main file, which handles input and output, is already provided. - Please only submit your class definitions, without any code outside the classes!
Implement three classes, Shape, Rectangle (which inherits from Shape), and Square (which inherits from Rectangle) in their own separate files, Shape in shape.py, Rectangle in rectangle.py and Square in square.py.
You should be able to figure out which methods you need to implement in these classes from the example execution code given below, which demonstrates what functionality these classes should offer.
Note:
-
The __str__() method should return the string: "{$C$} with area of {$A$} and perimeter of {$P$}." where $C$ is the name of the class, $A$ is the area of the shape, and $P$ is the perimeter. Both $A$ and $P$ should be limited to $2$ decimal places in this string. It does not matter whether you skip trailing zeros.
-
To get the name of the class you can use type(self).__name__. You could even hide that detail within yet another helper method.
This is an exercise in reusing methods in subclasses, so think about at which level in the hierarchy to implement each method, so that it can be used by other classes without the need to write the same code in multiple places. Also try to make your code extendable. For example, imagine we were to add a Circle class as well, or a Triangle class. What functionality would those have in common with the others?
Scoring
Each instance method is worth 10 points each, except the __str__ methods which are worth 20 points each.
Example usage
The following are examples of a main program.
Example 1
rect = Rectangle(2, 3) print(rect.get_area()) print(rect.get_perimeter()) print(rect) sq = Square(2) print(sq.get_area()) print(sq.get_perimeter()) print(sq)
Corresponding output:
6 10 Rectangle with area of 6.00 and perimeter of 10.00 4 8 Square with area of 4.00 and perimeter of 8.00
Example 2
rect = Rectangle(5, 10) print(f"Rectangle area: {rect.get_area()}") print(f"Rectangle perimeter: {rect.get_perimeter()}") print(rect) square = Square(7) print(f"Square area: {square.get_area()}") print(f"Square perimeter: {square.get_perimeter()}") print(square)
And the corresponding output:
Rectangle area: 50 Rectangle perimeter: 30 Rectangle with area of 50.00 and perimeter of 30.00 Square area: 49 Square perimeter: 28 Square with area of 49.00 and perimeter of 28.00
Hints
-
You only have to write the functions get_area() and get_perimeter() once such that it works for both Rectangle and Square.
-
The Shape class should not implement the get_area() and get_perimeter() methods, as we have no information on how to calculate the area and perimeter of a general undefined shape.
-
Only implement the __str__() method in the Shape class. If it calls methods that are only defined in the subclasses, that is fine as long as we never attempt to call the __str__() method directly on an instance of the Shape class, which we will not do.
This class is not intended to be used directly, only serve as a placeholder for common functionality of its derived classes.
-
The constructor of Shape can be more or less empty, using the pass statement.
Testing
Provided is a test file with unit tests that you can and should use to test your code locally before submitting your solution. It will provide you with quicker feedback, and more detail on what is going wrong, if anything. The test run upon submitting are different.