# 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.
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'
"""

@formatter
def diameter(self):
"""multiply radius by 2 to find diameter"""

@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.
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'
"""
self.height = float(height)

@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):

@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'
"""
self.depth = float(depth)

@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())
``````