Python Classes and Objects

Class Definition:

Class definition is a block of code that specifies a blueprint for developing items.

It defines the attributes and behaviors that the objects of the elegance can have.

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

    def bark(self):
        print(f"{self.name} says Woof!")
                                  
                                

  • The class key-word is used to outline a category.
  • The __init__ method is a constructor that initializes the item's attributes.
  • Self is a reference to the instance of the class.

Creating Objects:

Creating objects in Python entails instantiating a class.

An object is an example of a category, and the system of creating an item is regularly known as instantiation.

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

    def introduce(self):
        print(f"Hi, I'm {self.name} and I'm {self.age} years old.")

# Creating objects (instantiating the class)
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

# Accessing attributes and calling methods
person1.introduce()
person2.introduce()
                                  
                                

Class Variables and Instance Variables:

Class variables and example variables are used to shop records within a category, but they serve one of a kind functions and have exceptional scopes.

Class Variables:

Class variables are shared amongst all instances of a category. They are defined out of doors of any approach in the magnificence and are associated with the class itself in preference to with instances of the magnificence.

Class variables are regularly used to save data that is common to all times.

Example

                                  
                                    class Dog:
    # Class variable
    species = "Canine"

    def __init__(self, name, age):
        # Instance variables
        self.name = name
        self.age = age

# Accessing class variable
print(Dog.species)  # Outputs: Canine

# Creating objects
dog1 = Dog("Buddy", 3)
dog2 = Dog("Charlie", 5)

# Accessing class variable through instances
print(dog1.species)  # Outputs: Canine
print(dog2.species)  # Outputs: Canine
                                  
                                

In this example, species is a category variable shared via all times of the Dog magnificence.


Instance Variables:

Instance variables are specific to each example of a class. They are described inside the __init__ method and are prefixed with self. Each instance of the class may have extraordinary values for its example variables.

Example

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

# Creating objects
person1 = Person("Alice", 30)
person2 = Person("Bob", 25)

# Accessing instance variables
print(person1.name, person1.age)  # Outputs: Alice 30
print(person2.name, person2.age)  # Outputs: Bob 25
                                  
                                

In this example, call and age are instance variables that could have distinctive values for each instance of the Person class.

Inheritance:

Allows a brand new magnificence (subclass or derived class) to inherit attributes and behaviors from an present class (base elegance or discern elegance).

This promotes code reusability and permits for the advent of a hierarchy of classes.

                                      
                                        class Cat(Dog):
    def purr(self):
        print(f"{self.name} says Purr!")

cat1 = Cat("Whiskers", 2)
cat1.bark()  # Inherits the bark method from the Dog class
cat1.purr()  # New method specific to the Cat class
                                      
                                    

  • Inheritance lets in a class to inherit attributes and techniques from another elegance.

Encapsulation:

Encapsulation is one of the key ideas of item-orientated programming (OOP) and refers to the bundling of facts (attributes or variables) and strategies (features) that perform on the data into a single unit known as a class.

                                      
                                        class BankAccount:
    def __init__(self, balance):
        self.__balance = balance  # Private attribute

    def deposit(self, amount):
        if amount > 0:
            self.__balance += amount

    def withdraw(self, amount):
        if amount > 0 and amount <= self.__balance:
            self.__balance -= amount

    def get_balance(self):
        return self.__balance
                                      
                                    

  • Encapsulation includes bundling information (attributes) and strategies that perform on that facts inside a class.

Polymorphism:

Polymorphism is a fundamental idea in item-oriented programming (OOP) that allows items of different kinds to be dealt with as objects of a commonplace type. It enables a single interface to symbolize multiple underlying kinds.

There are fundamental styles of polymorphism:

  • Compile-time (or static) polymorphism
  • Runtime (or dynamic) polymorphism

Compile-time Polymorphism:

Compile-time polymorphism is finished thru technique overloading and operator overloading. Method overloading involves defining a couple of techniques with the identical name but distinctive parameter types or a unique number of parameters.

Python does support feature overloading, however it's primarily based on default argument values and variable-period argument lists.

                                      
                                        class MathOperations:
    def add(self, a, b):
        return a + b

    def add(self, a, b, c):
        return a + b + c

# Creating an object
math_obj = MathOperations()

# Overloaded methods
result1 = math_obj.add(2, 3)
result2 = math_obj.add(2, 3, 4)

print(result1)  # Outputs: TypeError (no method with two parameters)
print(result2)  # Outputs: 9
                                      
                                    

Runtime Polymorphism:

Method overriding takes place while a subclass provides a selected implementation for a way that is already described in its superclass.

This permits objects of the subclass to be used interchangeably with objects of the superclass.

                                      
                                        class Animal:
    def make_sound(self):
        print("Some generic animal sound")

class Dog(Animal):
    def make_sound(self):
        print("Woof!")

class Cat(Animal):
    def make_sound(self):
        print("Meow!")

# Creating objects
dog_obj = Dog()
cat_obj = Cat()

# Polymorphic behavior
dog_obj.make_sound()  # Outputs: Woof!
cat_obj.make_sound()  # Outputs: Meow!
                                      
                                    

In the example above, the make_sound method is overridden in both the Dog and Cat training. When calling make_sound on gadgets of the Animal superclass, the particular implementation in the respective subclass is executed, demonstrating runtime polymorphism.