Python Part 8: Object-Oriented Programming In Python (Classes and Objects)
Please Subscribe Youtube| Like Facebook | Follow Twitter
Object-Oriented Programming In Python
In this article, we will provide a detailed overview of Object-Oriented Programming In Python (Classes and Objects) and provide examples of how they are used in Python programming.
Python’s Object-Oriented Programming (OOP) is an incredible paradigm built upon four key pillars. These pillars, encapsulation, inheritance, polymorphism, and abstraction, provide a solid foundation for creating efficient and flexible code structures. In this article, we will explore the unique essence of each pillar and understand how they contribute to the power of Python’s OOP.
The Pillars of Object-Oriented Programming
OOP is built upon four key pillars: encapsulation, inheritance, polymorphism, and abstraction.
Encapsulation
Encapsulation in Python ensures data and behavior are bundled within classes, allowing controlled access and enhanced security. With access modifiers like public, private, and protected, Python enables developers to organize code effectively and protect sensitive information. This pillar strengthens data integrity and promotes modular code organization.
Inheritance
Python’s inheritance facilitates the creation of new classes by inheriting attributes and behaviors from existing ones. This pillar promotes code reuse, reduces redundancy, and fosters code evolution. With support for single and multiple inheritance, Python empowers developers to construct complex class hierarchies, establishing logical relationships between classes effortlessly.
Polymorphism
Polymorphism allows objects in Python to exhibit multiple forms and behaviors. Through dynamic typing, Python enables different classes to implement methods with the same name but with unique implementations. This feature enhances code flexibility, readability, and adaptability. Polymorphism empowers developers to write concise and modular code that accommodates diverse object types.
Abstraction
In Python, abstract classes and interfaces are not built-in language features like in some other programming languages such as Java or C#. However, Python provides a mechanism to define abstract classes using the abc (Abstract Base Classes) module, which can be used to achieve similar functionality.
We will explain them further in detail in next article. In this article we will explain Classes and Objects
Classes and Objects
In Python, a class is a blueprint for creating objects that share similar characteristics and behaviors. It defines a structure or template that describes the data attributes (variables) and methods (functions) associated with the objects. Objects, on the other hand, are instances of classes. They represent specific entities or things that can be manipulated and interacted with in your program.
Defining a Class
To define a class in Python, you use the class keyword followed by the class name. Let’s consider an example of a class called Car:
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
def start_engine(self):
print("Engine started!")
In the above code snippet, we define a class named Car that has three data attributes: make, model, and year. The init method is a special method called a constructor, which is executed automatically when an object is created from the class. It initializes the attributes of the object with the provided values. Additionally, we have defined a method named start_engine that simply prints a message indicating that the engine has started.
Creating Objects
Once we have defined a class, we can create objects (instances) of that class using the class name followed by parentheses. Let’s create a couple of Car objects:
car1 = Car("Toyota", "Corolla", 2022)
car2 = Car("Honda", "Civic", 2023)
In the above code, we create two instances of the Car class, namely car1 and car2. We pass the respective make, model, and year values as arguments to the class’s constructor (init method). Each object will have its own set of attributes, independent of other objects.
Fields (Instance Variables) in Python
Fields, also known as instance variables, store the state or data associated with objects. They hold unique values for each instance of a class. Fields are defined within a class and can be accessed and modified using the dot notation. Here’s an example:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"My name is {self.name} and I am {self.age} years old.")
In the above code snippet, we define a class called Person with two fields: name and age. The constructor __init__ method initializes these fields with the provided values. We also define an introduce method that prints a message introducing the person.
To access and modify the fields of an object, we use the dot notation:
person = Person("John", 25)
person.name = "Adam"
person.introduce() # Output: My name is Adam and I am 25 years old.
In the code above, we create an instance of the Person class called person with the name “John” and age 25. We then modify the name field to “Adam” and call the introduce method, which prints the updated introduction.
Methods in Python
Methods are defined within a class and are responsible for performing specific actions or tasks. They encapsulate behavior that objects of the class can exhibit. To define a method in Python, you use the def keyword followed by the method name and parentheses, optionally containing parameters. Here’s an example:
class Circle:
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return 3.14 * self.radius * self.radius
In the above code snippet, we define a class called Circle with two methods. The init method is a constructor, which we’ll discuss in more detail later. The calculate_area method calculates and returns the area of the circle using the radius attribute.
To access a method of an object, you use the dot notation, similar to accessing attributes:
circle = Circle(5) area = circle.calculate_area() print(area) # Output: 78.5
In the code above, we create an instance of the Circle class called circle with a radius of 5. We then call the calculate_area method of the circle object and store the result in the area variable. Finally, we print the calculated area, which is 78.5 in this case.
Constructors in Python
Constructors are special methods used to initialize objects. They have the same name as the class and are responsible for setting initial values to the object’s fields. In Python, constructors can take parameters, allowing you to pass values during object creation. Constructors can be categorized into two main types: no-argument constructors and parameterized constructors.
No-Argument/Non-Parameterized Constructors
A no-argument constructor does not take any parameters and initializes the parameters, providing default values for the object’s fields. Here’s an example:
class Rectangle: def __init__(self): self.width = 0 self.height = 0
In the above code snippet, we define a class called Rectangle with a no-argument constructor. The constructor initializes the width and height fields to 0.
Parameterized Constructors
A parameterized constructor, on the other hand, takes parameters that allow you to set specific initial values for the object’s fields. Here’s an example:
class Square:
def __init__(self, side_length):
self.side_length = side_length
In the code above, we define a class called Square with a parameterized constructor. The constructor takes a side_length parameter and assigns it to the side_length field.
To create objects using constructors, you simply call the class name followed by parentheses, passing the necessary arguments if required:
rectangle = Rectangle()
square = Square(5)
In the code snippet above, we create an instance of the Rectangle class called rectangle using the no-argument constructor. We also create an instance of the Square class called square using the parameterized constructor, passing the side length as 5.
self keyword
In Python, the ‘self’ keyword holds significant importance within the context of classes and objects. It is used as a convention to refer to the instance of a class within its own methods. The ‘self’ keyword allows you to access and manipulate the attributes and methods of an object.
When defining methods within a class, the first parameter is conventionally named ‘self’. This parameter represents the instance of the class itself. By using ‘self’, you can access the attributes and call the methods associated with that specific instance. Let’s consider an example:
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def introduce(self):
print(f"My name is {self.name} and I am {self.age} years old.")
In the code snippet above, we define a class named ‘Person’ with an ‘init‘ method and an ‘introduce’ method. The ‘init‘ method is a constructor that initializes the ‘name’ and ‘age’ attributes of the object. The ‘introduce’ method uses ‘self’ to access the ‘name’ and ‘age’ attributes and prints a formatted introduction.
To create an instance of a class and call its methods, we use the dot notation, along with the ‘self’ parameter implicitly passed. Here’s an example:
person = Person("John", 25)
person.introduce() # Output: My name is John and I am 25 years old.
In the code snippet above, we create an instance of the ‘Person’ class named ‘person’ with the name “John” and age 25. We then call the ‘introduce’ method of the ‘person’ object, which accesses the ‘name’ and ‘age’ attributes using ‘self’ and prints the formatted introduction.
Example Code
Here’s an example code snippet demonstrating the usage of classes, objects, and the ‘self’ keyword in Python, along with the corresponding output:
class Rectangle:
def __init__(self, length, width):
self.length = length
self.width = width
def calculate_area(self):
return self.length * self.width
def calculate_perimeter(self):
return 2 * (self.length + self.width)
# Creating instances of the Rectangle class
rectangle1 = Rectangle(4, 6)
rectangle2 = Rectangle(3, 5)
# Accessing attributes and calling methods
area1 = rectangle1.calculate_area()
perimeter1 = rectangle1.calculate_perimeter()
print("Rectangle 1:")
print("Area:", area1) # Output: Area: 24
print("Perimeter:", perimeter1) # Output: Perimeter: 20
area2 = rectangle2.calculate_area()
perimeter2 = rectangle2.calculate_perimeter()
print("\nRectangle 2:")
print("Area:", area2) # Output: Area: 15
print("Perimeter:", perimeter2) # Output: Perimeter: 16
Output
Rectangle 1: Area: 24 Perimeter: 20 Rectangle 2: Area: 15 Perimeter: 16
In the above code, we define a class called ‘Rectangle’ with attributes ‘length’ and ‘width’, as well as methods ‘calculate_area’ and ‘calculate_perimeter’. We then create two instances of the ‘Rectangle’ class, ‘rectangle1’ and ‘rectangle2’, with different length and width values.
We calculate and display the area and perimeter of ‘rectangle1’ and ‘rectangle2’ using the ‘calculate_area’ and ‘calculate_perimeter’ methods. The output shows the respective area and perimeter values for each rectangle.
Static Method And Non-Static Method In Python
Static Method
Static methods are methods that belong to the class itself, rather than an instance of the class. They do not operate on instance-specific data and do not require an instance of the class to be called.
Characteristics:
- Declared using the @staticmethod decorator.
- Can be called directly from the class itself without the need for an instance.
- Cannot access or modify instance attributes or methods.
- Typically used for utility functions or operations that are not tied to any specific instance.
Example:
class MathUtils:
@staticmethod
def add_numbers(a, b):
return a + b
result = MathUtils.add_numbers(5, 3)
print(result) # Output: 8
In the example above, we define a static method called ‘add_numbers’ within the ‘MathUtils’ class. This method takes two parameters, ‘a’ and ‘b’, and returns their sum. The static method is called directly from the class itself without creating an instance of the class.
Non-Static Methods (Instance Methods):
Non-static methods, also known as instance methods, are methods that require an instance of the class to be called. They operate on instance-specific data and can access instance attributes and other methods.
Characteristics:
- Defined without the @staticmethod decorator.
- Can only be called on instances of the class.
- Have access to instance attributes and methods using the ‘self’ keyword.
- Typically used to perform actions specific to individual instances of the class.
Example:
class Circle:
def __init__(self, radius):
self.radius = radius
def calculate_area(self):
return 3.14 * self.radius * self.radius
circle = Circle(5)
area = circle.calculate_area()
print(area) # Output: 78.5
In the example above, we define a class called ‘Circle’ with an instance method called ‘calculate_area’. This method uses the ‘self’ keyword to access the ‘radius’ attribute of the specific instance and calculates the area of the circle.
Differences between static and non-static methods In Python
Term | Static Method | Non-Static Method (Instance Method) |
---|---|---|
Declaration | Decorated with @staticmethod | Defined without decorator |
Calling Syntax | ClassName.methodName() | instance.methodName() |
Access to | No access to instance attributes or methods | Has access to instance attributes and methods |
Instance Specific Data | No | Yes |
Purpose | Utility functions, general operations | Actions specific to individual instances of class |
Conclusion
In conclusion, classes and objects are the fundamental building blocks of object-oriented programming (OOP). They enable us to organize and structure our code in a way that closely mirrors real-world entities and their interactions. By encapsulating data and behavior within classes, we can create objects that represent specific instances of those classes.
Classes act as blueprints or templates, defining the attributes (data) and methods (behavior) that objects of that class will possess. Objects, on the other hand, are instances of classes that have their own state and behavior.
Python Beginner Tutorial Series
- Python Part 1: Setup and Introduction
- Python Part 2: Understanding Basic Data Types And Variables In Python
- Python PART 3: OPERATORS AND EXPRESSIONS IN Python
- PYTHON PART 4: CONTROL FLOW STATEMENTS IN PYTHON
- Python PART 5: FUNCTIONS IN Python
- Python Part 6: Arrays and Lists In Python
- Python Part 7: String Manipulation In Python
- Python Part 8: Object-Oriented Programming In Python (Classes and Objects)
- Python Part 9: Object-oriented Programming In Python (OOP Pillars)
- Python Part 10: Exception Handling in Python