Chapter 7: Understand the Object-Oriented Approach in Python

Abstract:
Key points about using OOP in Python:
"self" keyword:
Within a class, "self" refers to the current object instance, allowing methods to access and modify the object's attributes. 
Constructor (__init__) method:
A special method called automatically when an object is created, usually used to initialize attributes. 
Dot notation:
To access an object's attributes or methods, use the dot notation (e.g., my_car.make). 
Benefits of OOP:
Code reusability:
Classes can be reused to create multiple objects with similar functionality. 
Modularity:
Code is organized into manageable units (classes), improving code readability and maintainability. 
Real-world modeling:
OOP allows you to represent real-world entities and their relationships in a structured way

Keywords :
Class, Object & Members in Python, Inheritance, Polymorphism, Encapsulation
Data Hiding & Object Printing
Constructors, Destructors in Python, Garbage Collection in Python

Learning Outcomes 
After undergoing this article you will be able to understand the 
Class, Object, and Members in Python 
Polymorphism, 
Encapsulation
Data Hiding & Object Printing, Garbage Collection in Python. 

Chapter 7: Class, Object, and Members in Python

Python is an object-oriented programming (OOP) language, which means it allows developers to design and build programs based on objects and their interactions. This chapter dives into the core OOP principles and explores how Python implements them.


7.1 Class, Object, and Members in Python

  • Class:
    A class is a blueprint for creating objects. It defines a set of attributes and methods that characterize any object of the class.
    Syntax:
class ClassName:
    # Attributes and methods
  • Object:
    An object is an instance of a class. When a class is defined, no memory is allocated until an object is created.
    Syntax:
obj = ClassName()
  • Class Members:
    • Attributes: Variables inside a class that represent data about the object.
    • Methods: Functions inside a class that define the behaviors of the object.
    • Access Modifiers: Determine the visibility of class members (public, _protected, __private).

Example:

class Person:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def greet(self):
        return f"Hello, my name is {self.name}."

# Creating an object
person1 = Person("Alice", 25)
print(person1.greet())  # Output: Hello, my name is Alice.

7.2 Inheritance

Inheritance allows a class (child) to inherit attributes and methods from another class (parent). It promotes code reuse and establishes a hierarchical relationship.

  • Syntax:
class Parent:
    # Parent class code

class Child(Parent):
    # Child class code

Example:

class Animal:
    def sound(self):
        return "This is a generic sound."

class Dog(Animal):
    def sound(self):
        return "Bark"

dog = Dog()
print(dog.sound())  # Output: Bark

7.3 Polymorphism

Polymorphism means "many forms." It allows methods in different classes to share the same name, offering flexibility.

Example:

class Bird:
    def fly(self):
        return "Some birds can fly."

class Penguin(Bird):
    def fly(self):
        return "Penguins cannot fly."

def flying_test(bird):
    print(bird.fly())

sparrow = Bird()
penguin = Penguin()

flying_test(sparrow)  # Output: Some birds can fly.
flying_test(penguin)  # Output: Penguins cannot fly.

7.4 Encapsulation

Encapsulation restricts direct access to some of an object's components, providing controlled access via methods. This is achieved using access modifiers.

  • Public Members: Accessible everywhere.
  • Protected Members: Prefix with _. Accessible in the class and its subclasses.
  • Private Members: Prefix with __. Accessible only within the class.

Example:

class Car:
    def __init__(self, brand, speed):
        self.brand = brand        # Public
        self._speed = speed       # Protected
        self.__engine_number = 12345  # Private

    def get_engine_number(self):
        return self.__engine_number

car = Car("Toyota", 120)
print(car.brand)           # Public access
print(car._speed)          # Accessible but discouraged
print(car.get_engine_number())  # Controlled access to private

7.5 Data Hiding & Object Printing

  • Data Hiding: Encapsulation aids in hiding implementation details. Only necessary information is exposed through methods.
  • Object Printing: By overriding the __str__ or __repr__ methods, we can customize object representation.

Example:

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author

    def __str__(self):
        return f"'{self.title}' by {self.author}"

book = Book("1984", "George Orwell")
print(book)  # Output: '1984' by George Orwell

7.6 Constructors

A constructor is a special method used to initialize objects. In Python, the __init__ method acts as the constructor.

Example:

class Student:
    def __init__(self, name, grade):
        self.name = name
        self.grade = grade

student = Student("John", "A")
print(student.name)  # Output: John

7.7 Destructors in Python

A destructor is used to perform cleanup operations when an object is deleted. Python provides the __del__ method as a destructor.

Example:

class File:
    def __init__(self, name):
        self.name = name

    def __del__(self):
        print(f"Closing file: {self.name}")

file = File("example.txt")
del file  # Output: Closing file: example.txt

7.8 Garbage Collection in Python

Python has an automatic garbage collection system that reclaims unused memory. The gc module provides tools for manual garbage collection.

Example:

import gc

# Enable garbage collection
gc.enable()

# Check if garbage collection is enabled
print(gc.isenabled())  # Output: True

7.9 Conclusions

Object-oriented programming in Python provides a structured and modular way to design software. Key principles such as inheritance, polymorphism, encapsulation, and data hiding allow for code reuse, flexibility, and robustness. Python’s support for constructors, destructors, and automatic garbage collection simplifies memory management, making it a powerful language for developing scalable and maintainable applications.

Comments