Object Oriented Programming (OOP)¶
OOP allows you to encapsulate specific behaviour into so called classes. Instances of those classes can be used to write intuitive program code. Below is an example using classes defined in rock.py to create instances of fruits and rocks and to determine their cumulative weight on a scale. Classes can represent real world objects as in this example but also abstract things like a button in a graphical user interface or a list with special sorting algorithms.
Normally you would import the classes from the module rock like this:
#from rock import Rock, Sediment, MagneticMatter, MagneticSediment, Scale, Fruit
Alternatively you can use the magic %load command to get the whole file into this ipython notebook:
# %load rock.py
# object oriented programming with Python
# Michael Wack 2015
class Fruit:
def __init__(self, weight):
self.weight = weight
def __repr__(self):
return( "fruit with weight {:.2e}".format( self.weight))
class Rock:
# class variable
rockcounter=0
@classmethod
def BlueRock(cls, weight, volume):
return cls( color="blue", weight=weight, volume=volume)
@staticmethod
def density( weight, volume):
return weight / volume
def __init__(self, color, weight, volume=11e-6):
self.color = color
self.weight = weight # SI: kg
self.volume = volume # SI: m^3
Rock.rockcounter += 1
self.no = Rock.rockcounter
print("{}. rock created".format(Rock.rockcounter))
def calculate_density(self):
return Rock.density( self.weight, self.volume) # SI: kg / m^3
def __repr__(self):
return( "{} rock (No {}) with a density of {:.2f}".format( self.color, self.no, self.calculate_density()))
class Sediment( Rock):
def __init__(self, color, weight, volume=11e-6, grainsize=0):
super().__init__(color, weight, volume)
self.grainsize = grainsize
def double_grainsize(self):
self.grainsize *= 2
def __repr__(self):
return( "{} sediment (No {}) with a density of {:.2e} and a grainsize of {:.2e}".format( self.color, self.no, self.calculate_density(), self.grainsize))
class MagneticMatter(): # all volume normalized
def __init__(self, magnetization=0, susceptibiltiy=0):
self.magnetization = magnetization # Am^2 / m^3 = A/m
self.susceptibility = susceptibiltiy # volume normailzed -> no units
def induced_magnetization(self, external_field_H): # SI A/m
return self.susceptibility * external_field_H
def total_magnetization(self, external_field_H): # SI A/m
return self.induced_magnetization(external_field_H) + self.magnetization
class MagneticSediment( MagneticMatter, Sediment):
def __init__(self, color, weight, volume, grainsize=0, magnetization=0, susceptibility=0):
MagneticMatter.__init__( self, magnetization, susceptibility)
Sediment.__init__( self, color, weight, volume)
def magnetic_moment(self):
return self.magnetization * self.volume
# class to determine weight of other object instances
class Scale():
def __init__(self, weight_limit=100):
self.weight_limit = weight_limit
self.instances = []
def put_on(self, inst):
if inst in self.instances:
print("{} is already on scale.".format(inst))
else:
self.instances.append(inst)
print("{} placed on scale.".format(inst))
def take_off(self, inst):
try:
self.instances.remove(inst)
print("{} removed.".format(inst))
except KeyError:
print("{} was not on scale.".format(inst))
@property
def weight(self):
weight = 0
for i in self.instances:
weight += i.weight
if weight > self.weight_limit:
print("Scale overloaded.")
return weight
apple = Fruit(weight=0.2)
apple
fruit with weight 2.00e-01
my_first_rock = Rock(color='red', weight=10)
1. rock created
my_first_rock
red rock (No 1) with a density of 909090.91
my_second_rock = Sediment(color='yellow', weight=12)
2. rock created
blue_rock = Rock.BlueRock(weight=3, volume = 0.1)
3. rock created
blue_rock
blue rock (No 3) with a density of 30.00
my_last_rock = MagneticSediment(color='purple', weight=1, volume=0.01, magnetization=1e-3, susceptibility=5e-3)
4. rock created
my_last_rock.induced_magnetization(external_field_H = 40)
0.2
my_last_rock.total_magnetization(external_field_H = 40)
0.201
myscale = Scale(weight_limit = 20)
myscale
<__main__.Scale at 0x7f45b01a36d8>
myscale.put_on( blue_rock)
blue rock (No 3) with a density of 30.00 placed on scale.
myscale.weight
3
myscale.put_on( my_second_rock)
yellow sediment (No 2) with a density of 1.09e+06 and a grainsize of 0.00e+00 placed on scale.
myscale.weight
15
myscale.put_on( my_second_rock)
yellow sediment (No 2) with a density of 1.09e+06 and a grainsize of 0.00e+00 is already on scale.
myscale.weight
15
myscale.put_on( my_first_rock)
red rock (No 1) with a density of 909090.91 placed on scale.
myscale.weight
Scale overloaded.
25
myscale.take_off( blue_rock)
blue rock (No 3) with a density of 30.00 removed.
myscale.weight
Scale overloaded.
22