7. Object oriented programming

In Python, you can easily create your on data type and populate them with variables (called attributes) and functions (called methods). This types are called classes (see footnote 1).

Consider for instance the built-in class dict which we already discussed. You get an instance of dict, that is an object with type dict, by calling:

In [1]:
some_instance_of_dict = dict(ad = "something", ot = "some other thing")

Which, of course, is equivalent to the one we already saw:

In [2]:
some_instance_of_dict = {"ad": "something", "ot": "some other thing"}

And as we have seem, dict (and other types like list) has its own set useful method that we can call, like pop, which removes one of its elements:

In [3]:
some_instance_of_dict = dict(ad = "something", ot = "some other thing")
some_instance_of_dict.pop("ad")
some_instance_of_dict
Out[3]:
{'ot': 'some other thing'}

7.1. A custom class

So, as promised here’s a way to create your class:

In [4]:
class Car:
    def __init__(self, color):
        self.color = color

You can them create some instances of Car, that is, objects which has type Car.

In [5]:
car1 = Car("blue")
car2 = Car("red")

print("car1 has color: ", car1.color)
print("car2 has color: ", car1.color)

print(type(car1))
car1 has color:  blue
car2 has color:  blue
<class '__main__.Car'>

Now, let’s analyse the code of Class car: init is a method that is called once you create the object and receives as the first argument the object itself (by convention called self) and possibly other optional arguments. The line self.color = color creates an attribute color.

Here’s another example, take some time to explore it a little:

In [6]:
class Car:
    def __init__(self, color, initial_speed = 10):
        self.color = color
        print("Car engine starting!")
        self.speed = initial_speed

    def increase_speed(self):
        self.speed += 30
        return self.speed

car1 = Car("blue")
car2 = Car("red", 20)

print("Speed of car1 is: ", car1.increase_speed())
print("Speed of car1 is: ", car1.increase_speed())
print("Speed of car1 is: ", car1.increase_speed())
print("Speed of car1 is: ", car1.speed)
print("Speed of car1 is: ", car1.speed)

print("Speed of car2 is: ", car2.increase_speed())
print("Speed of car2 is: ", car2.increase_speed())
print("Speed of car2 is: ", car2.speed)
print("Speed of car2 is: ", car2.speed)
Car engine starting!
Car engine starting!
Speed of car1 is:  40
Speed of car1 is:  70
Speed of car1 is:  100
Speed of car1 is:  100
Speed of car1 is:  100
Speed of car2 is:  50
Speed of car2 is:  80
Speed of car2 is:  80
Speed of car2 is:  80

7.2. Inheritance

Classes can inherit from other classes as well, allowing you to reuse methods already defined. Consider this example:

In [7]:
class Car:
    def __init__(self, color, initial_speed = 10):
        self.color = color
        print("Car engine starting!")
        self.speed = initial_speed

    def increase_speed(self):
        self.speed += 30
        return self.speed

class Pickup(Car):
    def load_cargo(self, initial_weight=100):
         self.weight = initial_weight

    def load_more_cargo(self, additional_weight=100):
         self.weight += additional_weight

    def unload_some_cargo(self, weight_to_decrease=100):
         self.weight -= weight_to_decrease

class Sports(Car):
    def __init__(self, color, initial_speed = 1000):
        self.color = color
        print("Car engine starting!")
        self.speed = initial_speed

    def increase_speed(self):
        self.speed += 300
        return self.speed

car1 = Car("blue")
car2 = Pickup("red", 20)
car3 = Sports("red")

type(car1)
type(car2)
type(car3)
Car engine starting!
Car engine starting!
Car engine starting!
Out[7]:
__main__.Sports

We can then play with speed for any of them:

In [8]:
print("Speed of car1 is: ", car1.increase_speed())
print("Speed of car1 is: ", car1.increase_speed())
print("Speed of car1 is: ", car1.speed)

print("Speed of car2 is: ", car2.increase_speed())
print("Speed of car2 is: ", car2.increase_speed())
print("Speed of car2 is: ", car2.speed)
print("Speed of car2 is: ", car2.speed)

print("Speed of car3 is: ", car3.increase_speed())
print("Speed of car3 is: ", car3.increase_speed())
print("Speed of car3 is: ", car3.speed)
print("Speed of car3 is: ", car3.speed)

print("Speed of car3 is: ", car3.speed)
Speed of car1 is:  40
Speed of car1 is:  70
Speed of car1 is:  70
Speed of car2 is:  50
Speed of car2 is:  80
Speed of car2 is:  80
Speed of car2 is:  80
Speed of car3 is:  1300
Speed of car3 is:  1600
Speed of car3 is:  1600
Speed of car3 is:  1600
Speed of car3 is:  1600

But, we can also load some cargo on the Pickup

In [9]:
car2.load_cargo(100)
print("Current cargo weight for car2: ", car2.weight)
car2.load_more_cargo(1000)
print("Current cargo weight for car2: ", car2.weight)
car2.unload_some_cargo(100)
print("Current cargo weight for car2: ", car2.weight)
Current cargo weight for car2:  100
Current cargo weight for car2:  1100
Current cargo weight for car2:  1000

7.3. Footnotes

  1. Type and class can be considered to be synonymous in Python.