Reputation: 81
class Body(object)
I have a parent class characterising the classical mechanics definition of a physical body. Such as it is, this parent class has the attributes: name, mass, position, velocity.
from Utilities import *
class Body(object):
'''
In classical mechanics a physical body is collection of
matter having properties including mass, velocity, momentum
and energy. The matter exists in a volume of three-dimensional
space called its extension.
'''
def __init__(self, name, mass):
if isinstance(name, str) and isinstance(mass, float):
#Name
self.name = name
#Mass
self.mass = mass
#Position record
self.positions = np.empty(shape = (0, 3), dtype = float)
#Velocity record
self.velocities = np.empty(shape = (0, 3), dtype = float)
pass
else:
raise TypeError('Name and mass must be string and float, respectivly.')
return None
class Planet(Body)
Additionally, I have a child class characterising Planets, which are fundamentally physical bodies, and thus should inherit the abstract physical attributes of such, namely: name, mass, position, velocity.
class Planet(Body):
def __init__(self, name, mass = float):
self.mass = Planet_Mass(name)
Body.__init__(self, name, self.mass)
#Import the necesary modules
from context import Planet
#Instantiate Earth as a massive celestial object
Earth = Planet('Earth')
#Print the mass of the planet [10^24 kg]
print 'The mass of Earth is: ', Earth.mass, ' [10^24 kg]'
The mass of Earth is: 5.97 [10^24 kg]
Fundamentally, all physical bodies have mass. However, in the context of this simulation, the method by which mass is determined differs between the various child classes of class Body(object)
, namely: class Planet(Body)
, class Satellite(Body)
, etc.
class Planet(Body)
, mass is determined via Planet_Mass(name)
, which involves reading through a planetary fact sheet .txt file.class Satellite(Body)
, mass is determined via Satellite_Mass(name)
, which involves reading through a satellite fact sheet .txt file. Is there anyway to alter the initialisation of my child classes to be less redundant?
Essentially, I would like to remove the necessity of stating self.mass = Planet_Mass(name)
in class Planet(Body)
.
Upvotes: 2
Views: 2423
Reputation: 184101
Don't accept mass
in your Planet class constructor since you're not going to use it.
Don't set self.mass
in your Planet class constructor since the parent constructor does it.
class Planet(Body):
def __init__(self, name):
Body.__init__(self, name, Planet_Mass(name))
If you do want to accept mass
in your Planet class and allow it to override the mass from the lookup table (or maybe some planets aren't in the lookup table), do it like this:
class Planet(Body):
def __init__(self, name, mass=None):
if mass is None:
Body.__init__(self, name, Planet_Mass(name))
else:
Body.__init__(self, name, mass)
earth = Planet("Earth")
trantor = Planet("Trantor", 1.792e25) # Asimov's Trantor; ~3x Earth mass
If you want to go further and avoid the if
statement in your subclasses' __init__
then you can put the desired behavior on the Body
class. The basic idea is that you define a method to calculate the mass from the name. On the base class, this method would do nothing. On your subclasses, it gets the mass from the lookup table. Then you don't even need __init__
in your subclasses.
class Body(object):
def __init__(self, name, mass=None):
if mass is None:
mass = self._name2mass(name)
# followed by the argument checking and attribute setting
# especially, you must check that mass is not None
@staticmethod
def _name2mass(name): return None
class Planet(Body):
@staticmethod
def _name2mass(name): return Planet_Mass(name)
# or just implement Planet_Mass here!
I've used @staticmethod
because looking up a body's mass by its name does not require access to the instance (or the class, for that matter).
Upvotes: 3