Table of contents:
- Chapter 7.1 Object-Oriented Programming (OOP)
An Object oriented programming (OOP) is a computer programming model that organizes the code block around data rather than functions. In functional programming approach, data and function act as different entity whereas an OOP approach uses a block of code that contains both data and methods that operate on those data.
An object-oriented programming covers the limitations of functional programming by structuring the data and binding the methods to specific object rather than creating an independent functional block.
Example 1:
height = 50
temperature = 90
def add_values(a, b):
return a + b
print(height + temperature)
In the above example, height
can be added with temperature
since they both
are integers, but there is no sense adding those values. There is no binding
of the function add_values()
to those data. Furthermore, if we had 2 different
values for height, subtracting one from another would give negative value, which
would also be illogical since there can not be negative height. If we solve the
same problem using and OOP approach, the method would be bound to specific data,
and we could define specific attributes to those data.
An object-oriented programming contains different elements which are as follows:
- Classes: Classes are user-defined data types that acts as a blueprint for individual objects.
- Objects: Objects are instances of a class that contains specific data. Generally objects can represent real-world objects such as human, room, etc.
- Methods: Methods are functions that are bound to specific objects. For
example, a
human
object can havetalk
method, whereas a computer object can haveboot
method. - Attributes: Attributes are variables that define the property of an object
Attributes can also be defined as a state of an object for example, if we
create an object for a
rectangle
, thenlength
andwidth
will be attributes for it.
An object-oriented programming features those things that can reflect real-world objects. If we take an example of road-based vehicles, they can be cars, buses, motorbikes, etc which share some attributes whereas some has different attributes all of these can be represented with the following:
- Inheritance
- Polymorphism
- encapsulation
- objects
- Data Abstraction
A class is a building block of an OOP. A class creates a block of a code that is used to bind attributes to its methods. Class works just like a group or a container that contains different variables and functions.
Python classes can be created using a class
keyword.
- Class names should be written in
UpperCamelCase
. - Class attributes and methods should be written in
snake_case
. - We should separate classes with 2 blank lines and methods with a blank line.
- objects or instances are defined with
snake_case
representation as in variables.
A Basic Example:
class Person:
first_name = 'John'
last_name = 'Doe'
def show_full_name(self):
return f'{self.first_name} {self.last_name}'
The above example uses first_name
and last_name
as attributes of the class
Person
whereas show_full_name()
as the method that binds to the person
self
is just an identifier or a variable name that holds the instance of
the class. self
is not a python keyword and can be replaced with any other
identifier, but to make code consistent, pep-8 prefers using self
as the
first parameter.
Classes are made up of the following building blocks:
- Attributes
- Class Attributes
- Instance Attributes
- Methods
- Instance Methods (Bounded to the instance)
- Class Methods (Bounded to the class)
- Static Methods (Unbounded methods)
- Initializer method (called upon creation of the instance)
- Instance
- All the variables defined inside a class are attributes.
- Attribute acts as a state of the class which changes over time and condition
- All functions defined inside a class are known as methods
- All instance methods use
self
as the first parameter which references the instance itself. - the
__init__()
method do not need to be called and gets automatically called once the object gets initialized.
class Person:
species = 'Human' # Class Attribute
def __init__(self, first_name, last_name): # initializer method
self.first_name = first_name # Instance Attribute
self.last_name = last_name
def fullname(self): # method
print(f"{self.first_name} {self.last_name}")
The constructor method is a method that initializes the class. in python,
__init__()
method is used as a constructor method which prototypes an instance
of the class. When we create an object of the class, the __init__()
method is
called first. The __init__()
method also requires self
as the first
parameter.
To initialize a class, we write the name of the class along with parameters
that is accepted by an initializer class. The example below uses a class
Person
with the initializer method that accepts first_name
, and last_name
.
The self
parameter is itself passed by the class whenever it is called. The
instance perspn_1
is a variable that has all the features that are prototyped
by the class Person
.
class Person:
species = 'Human' # Attribute
def __init__(self, first_name, last_name): # initializer method
"""
This initializer method is called automatically when we create an instance
of the class. The parameters that is required in the `__init__()` method
should be passed while instantiating an object of the class.
"""
print("Hi I am Initialized")
self.first_name = first_name
self.last_name = last_name
def fullname(self): # method
print(f'{self.first_name} {self.last_name}')
# The `Person` takes 2 arguments while initializing since the `__init__()`
# method requires 2 arguments `first_name` and `last_name`.
person_1 = Person('John', 'Doe')
# prints out "Hi I am Initialized"
Here, the statement, self.first_name = first_name
will set the first name
for an instance person_1
once person_1 = Person('John', 'Doe')
gets
executed.
We use .
notation to access attributes and methods of the instance.
for example, to access first_name
, we can write person_1.first_name
.
person = Person('John', 'Lennon')
# Accessing the attribute
print(person.first_name) # John
# Accessing the method
print(person.full_name()) # John Lennon
Note: Even though methods has
self
as the first parameter, we do not need to pass theself
argument manually to call the function. It automatically gets passed by the python interpreter in the time of calling.Also, the
self
parameter is only accessed inside the class body and has special privilege to access all the private and protected attributes of the class.
Those Attributes that are declared during the class definition are known as class attributes. The class attribute points out the class and is accessible even before initialization of the class.
On the other hand, Instance attributes are declared inside the __init__()
method and are only accessible after initializing the class.
If we want to declare an instance attribute, we need to define an attribute
using self
annotation otherwise it would create a local variable instead of an
instance attribute.
The example below shows different attributes declared within a class.
class Animal:
category = 'Vertebrate' # Class Attribute
legs = 4
def __init__(self, name, child):
self.name = name # Instance Attribute
self.child = child
word = 'Moo' # Local variable (Inaccessible outside of a method)
print(Animal.category) # Vertebrate
cow = Animal(name='My Cow', child='calf')
print(cow.name) # My Cow
-
To access the class attribute
category
, we do not need to instantiate the class. -
To access the instance attribute
name
, we need to instantiate the class by usingAnimal(name='My Cow', child='calf')
-
If we try to access the instance attribute
name
without initializing the -
class, it raises an
AttributeError
exception.type object 'Animal' has no attribute 'name'
as below.
>>> print(Animal.name)
Traceback (most recent call last):
File "<pyshell#3>", line 1, in <module>
Animal.name
AttributeError: type object 'Animal' has no attribute 'name'
Python classes has some built-in attributes which will be available to all classes. some of the attributes are as follows:
object.__str__()
: returns the readable string representation of the objectobject.__repr__()
: returns the unambiguous string representation similar to the__str__()
method.object.__dict__
: the dictionary representation of the objectobject.__doc__
: the documentation string of the classobject.__sizeof__()
: returns the size of object in bytes
Example:
class Person:
"""
The class Person stores the first_name, last_name, and age of a
person once initialized.
"""
def __init__(self, first_name, last_name, age):
self.first_name = first_name
self.last_name = last_name
self.age = age
def __str__(self):
return f'Person<{self.first_name}>'
john = Person('John', 'Lennon', 50)
print('The String Representation is:', john.__str__())
print('The dictionary representation is:', john.__dict__)
print('The document string is:', john.__doc__)
print('The size of a class is:', john.__sizeof__())
Output:
The String Representation is: Person<John>
The dictionary representation is: {'first_name': 'John', 'last_name': 'Lennon', 'age': 50}
The document string is:
The class Person stores the first_name, last_name, and age of a
person once initialized.
The size of a class is: 32
In python, everything are objects. Even basic data types such as int
, float
,
etc. are also represented using classes.
Example:
x = 5
print(type(x))
# <class 'int'>
Here x
is an object of a class int
. Hence it inherits all the properties and
features defined in the class int
.
In python once we initialize a class and assign the instance to the variable, the variable is called as an object or instance. for example:
class Animal:
def __init__(self, name, word):
self.name = name
self.word = word
def speak(self):
print(f'I speak with {self.word}')
cow = Animal('My Cow', 'Moo')
Here cow
is an instance of Animal()
hence cow
inherits all properties of
the class Animal
such as speak()
.