playing with circles
I decided to tinker with inheritance, decoration and using command line arguments. My subject of choice, Circles!
To run the following script at command line:
E.g.
python circles.py 1 1 1
Import to use in a python shell:
from circles import *
c1 = Circle(1)
c2 = Circle3D(1, 1)
c3 = Ellipsoid(1, 1, 1)
#functions
help(c1) #etc
#E.g.
c1.area()
c2.cone_volume()
c3.ellipse_volume()
the code
#!/usr/bin/python3
"""
This module is my example of decoration and inheritance.
Interesting feature of this code is the use of @wraps from functools to ensure the
method docstrings are passed through decoration.
This module includes 3 classes providing methods for analysing 1d, 2d and 3d circle objects.
1) Circle: diameter, area, perimeter
2) Circle3D: introduces height dimension and calculates things like a cone or cylinder
3) Ellipsoid: Introduces a third variable, depth, to calculate an ellipsoidal shape.
"""
# import modules
import math
from functools import wraps
# decorator to pretty print
def formatter(func):
@wraps(func)
def inner(*args):
return "{} = {:.2f}".format(func.__name__, func(*args))
return inner
class Circle(object):
"""
Create a circle and calculate attributes.
Requires 1 argument: radius
Result is a formatted string: 'method = value'
Examples
>>> Circle(1).diameter()
'diameter = 2.00'
>>> Circle(1).area()
'area = 9.87'
>>> Circle(1).perimeter()
'perimeter = 6.28'
"""
def __init__(self, radius):
self.radius = float(radius)
@formatter
def diameter(self):
"""multiply radius by 2 to find diameter"""
return self.radius * 2
@formatter
def area(self):
return (math.pi * self.radius) ** 2
@formatter
def perimeter(self):
return (2 * math.pi) * self.radius
class Circle3D(Circle):
"""
Calculate 3 dimensional attributes by building on to the Circle class.
Requires 2 arguments: radius, height
Result is a formatted string: 'method = value'
Examples
>>> Circle3D(1,1).cylinder()
'cylinder = 3.14'
>>> Circle3D(1,1).cone_volume()
'cone_volume = 1.05'
>>> Circle3D(1,1).cone_area()
'cone_area = 7.58'
>>> Circle3D(1,1).sphere_volume()
'sphere_volume = 4.19'
>>> Circle3D(1,1).sphere_area()
'sphere_area = 12.57'
"""
def __init__(self, radius, height):
self.height = float(height)
super(Circle3D, self).__init__(radius)
@formatter
def cylinder(self):
return (math.pi * (self.radius ** 2)) * self.height
@formatter
def cone_volume(self):
return 1/3 * (math.pi * (self.radius ** 2)) * self.height
@formatter
def cone_area(self):
return math.pi * self.radius * (self.radius + math.sqrt(self.height**2 + self.radius**2))
@formatter
def sphere_volume(self):
return (4/3) * (math.pi * (self.radius ** 3))
@formatter
def sphere_area(self):
return 4 * (math.pi * (self.radius ** 2))
class Ellipsoid(Circle3D):
"""
Calculate area and volume of an ellipse and ellipsoid.
Requires 3 arguments: radius, height and depth
depth is required for calculating volume of ellipsoid.
radius and depth define the cross section of the ellipse.
height defines the overall length/latidudinal dimension.
Examples
>>> Ellipsoid(1,1,1).ellipse_area()
'ellipse_area = 1.57'
>>> Ellipsoid(1,1,1).ellipse_volume()
'ellipse_volume = 2.09'
"""
def __init__(self, radius, height, depth):
self.depth = float(depth)
super(Ellipsoid, self).__init__(radius, height)
@formatter
def ellipse_area(self):
return math.pi * self.radius * (self.height / 2)
@formatter
def ellipse_volume(self):
return (4/3) * math.pi * (self.height / 2) * self.radius * self.depth
if __name__ == "__main__":
import math, sys, doctest
doctest.testmod()
circ = Ellipsoid(sys.argv[1], sys.argv[2], sys.argv[3])
print(circ.diameter())
print(circ.area())
print(circ.perimeter())
print(circ.cylinder())
print(circ.cone_volume())
print(circ.cone_area())
print(circ.sphere_volume())
print(circ.sphere_area())
print(circ.ellipse_area())
print(circ.ellipse_volume())