class FiatUno:
def __init__(self, color="white", radio=False):
self.color = color
self.radio = radio
self.radio_is_on = False
def turn_on_radio(self):
self.radio_is_on = True
print(f"Radio is on!")
def turn_off_radio(self):
self.radio_is_on = False
print(f"Radio is off!")
9 Object Oriented Programming
9.1 Classes and Objects
In python we deal with so-called objects. An object is an instance, that is a particular realization, of a class.
Here’s an analogy: You can think of a class as the instructions to build a car, say a FiatUno:
By convention, we use CamelCase to name classes.
Each actual car is an object, i.e. an instance of a class:
= FiatUno() car1
We can make another car:
= FiatUno() car2
Like two cars can be the same model and color, they always have different license plates.
The same happens in python:
id(car1)
139856081602784
id(car2)
139856081603648
Each object has attributes:
car1.color, car1.radio
('white', False)
9.2 Methods
Different car models have different functionalities, like turning the radio on.
In python it’s the same, the functions attached to an object are called methods and we call them with this dot notation:
# it's just a function, so we call it with () car1.turn_on_radio()
Radio is on!
car1.turn_off_radio()
Radio is off!
Where is the self argument of the functions?
The first argument of a method will be always passed to the method in the call and it is the object itself (thus the convention to call it self).
That’s a bit meta an a bit confusing, but don’t worry, you’ll get a feel of it by using the classes/objects.
9.3 Dunder Methods
We saw above the __init__
method. This methods are special and there is a bunch of them already present on all classes:
dir(FiatUno)
['__class__',
'__delattr__',
'__dict__',
'__dir__',
'__doc__',
'__eq__',
'__format__',
'__ge__',
'__getattribute__',
'__gt__',
'__hash__',
'__init__',
'__init_subclass__',
'__le__',
'__lt__',
'__module__',
'__ne__',
'__new__',
'__reduce__',
'__reduce_ex__',
'__repr__',
'__setattr__',
'__sizeof__',
'__str__',
'__subclasshook__',
'__weakref__',
'turn_off_radio',
'turn_on_radio']
These “dunder” methods define the behavior of the object in several ways. For example, the __str__
method defines the string representation of the object, which is used when we call print
on an object. When we do print(something)
, python actually goes to the method __str__
of something and calls that one. Let’s see it in action:
class A:
def __init__(self, msg="hello"):
self.msg = msg
def __str__(self):
return self.msg + ", nice to meet you"
= A() a
print(a)
hello, nice to meet you
It’s good to know that these dunder methods exist and some libraries will require the user changing them. But in general, you should not worry about them.
Don’t overwrite dunder methods unless you really, really need it and you’re sure what you’re doing – it is pretty easy to make mistakes that lead to difficult to debug bugs.
9.4 Inheritance
Avoid using inheritance. We show it here just for you to know it exists and that some libraries use it. You can totally live without it.
Classes can be organized in a hierarchy:
class Car:
def __init__(self):
self.n_wheels = 4
class FiatPalio(Car):
def turn_on_radio(self):
print("Radio is on")
class FiatTipo(Car):
def turn_on_ac(self):
print("Pretty hot in here")
= FiatPalio()
car3 = FiatTipo() car4
car3.turn_on_radio()
Radio is on
car3.n_wheels
4
car4.turn_on_ac()
Pretty hot here
car4.n_wheels
4
In that case Car
is called the “parent” class and the FiatPalio
the “child” or “subclass”.
Notice that both car3
and car4
inherited the attribute n_wheels
from Car
.
A class can have more than one parent:
class Parent1:
= 2
n_arms
class Parent2:
= 2
n_legs
class Parent3:
= 2
n_eyes
class Child(Parent1, Parent2, Parent3):
def list_body_parts(self):
print("arms: ", self.n_arms)
print("legs: ", self.n_legs)
print("eyes: ", self.n_eyes)
= Child() child
child.list_body_parts()
arms: 2
legs: 2
eyes: 2
Multiple inheritance is also tricky and you should avoid it. It’s just good to know it exists to understand code from out there, for example, the popular scikit-learn
library uses this a lot to propagate methods and avoid code duplication.