Web Development
HTML Course
CSS Course
JavaScript Course
PHP Course
Python Course
SQL Course
SEO Course

Object-Oriented Programming (OOP)

Classes and Objects in Python

Object-oriented programming (OOP) is a programming style that organizes code around "objects" - instances of classes. A class defines structure and behavior, while objects are concrete instances of this structure.

Defining a class

class Student:
    pass

Creating an object

John = Student()
print(type(John))   # Output: <class '__main__.Student'>
Note:
  • A class is a user-defined data type.
  • Objects are instances of classes and can have their own attributes and methods.
  • With OOP, code becomes more modular, reusable, and easier to maintain.

The __init__ Constructor in Python

The __init__ method is the constructor of a class in Python. It is called automatically when an object is created and allows attribute initialization.

Defining a constructor

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

Creating an object with a constructor

John = Student("John", 17)
print(John.name)     # Output: John
print(John.age)      # Output: 17
Note:
  • self is a reference to the current instance of the class.
  • The constructor can accept any number of parameters, depending on what you want to initialize.
  • Without __init__, the object is created but has no defined attributes.

Attributes and Methods in Python

Attributes are variables associated with an object, while methods are functions defined within a class. They define the state and behavior of objects.

Instance attributes

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

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

Instance methods

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

    def greet(self):
        print(f"Hello, I am {self.name}!")

John = Student("John")
John.greet()   # Output: Hello, I am John!
Note:
  • Attributes define the state of an object.
  • Methods define behavior and can access attributes via self.
  • You can modify attributes directly: John.age = 18.

Inheritance and Polymorphism in Python

Inheritance allows a class to acquire the behavior and attributes of another class. Polymorphism allows using the same methods in different ways depending on the object context.

Class inheritance

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

    def greet(self):
        print(f"Hello, I am {self.name}")

class Student(Person):
    def greet(self):
        print(f"Student {self.name} says hello!")

Polymorphism

pers = Person("Anna")
student = Student("John")

pers.greet()    # Hello, I am Anna
student.greet() # Student John says hello!
Note:
  • Inheritance is done using parentheses: class Subclass(BaseClass).
  • Methods can be overridden in the subclass for customized behavior.
  • Polymorphism allows handling different objects through the same interface.

Encapsulation and Properties in Python

Encapsulation is the OOP principle that protects the internal data of an object. In Python, we can control access to attributes using conventions and properties.

Private attributes (convention)

class Student:
    def __init__(self, name):
        self._name = name   # convention: "protected" attribute
        self.__code = 1234  # "private" attribute (name mangling)

Controlled access with properties

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

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        if value:
            self._name = value

John = Student("John")
print(John.name)     # Output: John
John.name = "Andrew"
print(John.name)     # Output: Andrew
Note:
  • Attributes with _ or __ are not completely private, but signal protection intent.
  • Decorators @property and @setter allow control over reading and modifying attributes.
  • Encapsulation helps maintain data integrity and hide internal details.

Special Methods (dunder methods) in Python

Special methods, also known as "dunder methods" (double underscore), allow defining custom behavior for objects in common contexts: display, length, addition, etc. They start and end with two underscore characters.

__str__ - textual representation

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

    def __str__(self):
        return f"Student: {self.name}"

John = Student("John")
print(John)   # Output: Student: John

__len__ - object length

class Group:
    def __init__(self, members):
        self.members = members

    def __len__(self):
        return len(self.members)

g = Group(["John", "Anna", "Michael"])
print(len(g))   # Output: 3

__add__ - behavior of the + operator

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

    def __add__(self, other):
        return f"{self.name} and {other.name} are classmates"

e1 = Student("John")
e2 = Student("Anna")
print(e1 + e2)   # Output: John and Anna are classmates
Note:
  • Special methods allow natural integration of objects into Python expressions.
  • __str__ is used by print() for display.
  • __len__ allows using the len() function on custom objects.
  • __add__ defines how objects behave when added with +.

๐Ÿง  Quiz - Object-Oriented Programming (OOP)

Top