
Object (Instance):
A specific entity that is created following a blueprint (class).
It holds data (variables) and functions (methods) to manipulate that data.
Class: The blueprint or template used to create objects. It defines the structure and behaviors that its instances will have.
Object-Oriented Programming (OOP): A programming paradigm that organizes code by bundling data and behavior into objects.
Benefits of OOP include reusability, maintainability, and extensibility of code.
For example, you can have a Car class that serves as a blueprint for creating different car objects, each with its own unique properties.
In Python, you define a class using the class keyword:
class ClassName:
# class variables
# methods (functions) go here
Naming Convention: By convention, class names in Python typically use CamelCase (e.g., MyClass, StudentInfo, Car).
class Animal:
species = "Animal" # Class variable
def __init__(self, name, age):
# Instance variables
self.name = name
self.age = age
This special method is automatically called when a class is instantiated (i.e., when you create an object). It is commonly used to initialize instance variables.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
# Usage
p = Person("Alice", 25) # __init__ is called automatically
print(p.name) # Alice
print(p.age) # 25
Called automatically when an instance is about to be destroyed. Python uses garbage collection, so you rarely need to manually free memory. Destructors are typically used for releasing external resources if necessary.
class Person:
def __init__(self, name):
self.name = name
def __del__(self):
print(f"Instance of {self.name} is being destroyed.")
class MyClass:
# Class variable
class_var = "This is a class variable"
def __init__(self, value):
# Instance variable
self.value = value
def instance_method(self):
"""
An instance method can access both
instance variables and class variables.
"""
print(f"Instance method: self.value = {self.value}")
print(f"Instance method: MyClass.class_var = {MyClass.class_var}")
@classmethod
def class_method(cls):
"""
A class method can access the class
(and thus class variables), but not specific instances.
"""
print(f"Class method: cls.class_var = {cls.class_var}")
@staticmethod
def static_method():
"""
A static method does not take self or cls.
It's essentially a regular function inside the class namespace.
"""
print("Static method called")
Single underscore (_var or _method): Indicates the attribute or method is for internal use only; other developers are discouraged from using it directly.
Double underscore (__var or __method): Indicates even stronger intent for internal use only. Python performs name mangling in this case, though it’s still accessible if you know how (e.g., _ClassName__var).
class MyClass:
def __init__(self):
self.public_var = "public variable"
self._internal_var = "internal variable (not recommended to use externally)"
self.__secret_var = "private variable"
def public_method(self):
print("Public method")
def _internal_method(self):
print("Internal method")
def __secret_method(self):
print("Secret method")
Allows a new class (child or subclass) to inherit attributes and methods from an existing class (parent or superclass).
Enhances code reusability and helps maintain a clear hierarchy.
class ParentClass:
def parent_method(self):
print("Parent class method")
class ChildClass(ParentClass):
def child_method(self):
print("Child class method")
A subclass can override (redefine) a method from its superclass.
class Animal:
def speak(self):
print("Animals can make sounds.")
class Dog(Animal):
def speak(self):
print("Woof!") # Overrides the parent speak method
dog = Dog()
dog.speak() # Woof!
Used to call the parent class’s methods from the child class:
class Animal:
def __init__(self, name):
self.name = name
class Dog(Animal):
def __init__(self, name, breed):
super().__init__(name) # Call the parent constructor
self.breed = breed
Polymorphism means different classes can define the same method in different ways:
class Cat:
def speak(self):
print("Meow")
class Dog:
def speak(self):
print("Woof")
def make_sound(animal):
animal.speak()
cat = Cat()
dog = Dog()
make_sound(cat) # Meow
make_sound(dog) # Woof
class BankAccount:
# Class variable (e.g., an interest rate that applies to all accounts)
interest_rate = 0.02
def __init__(self, owner, balance=0):
self.owner = owner
self.balance = balance
def deposit(self, amount):
"""Deposit method"""
self.balance += amount
print(f"Deposited {amount}. New balance: {self.balance}")
def withdraw(self, amount):
"""Withdraw method"""
if self.balance >= amount:
self.balance -= amount
print(f"Withdrew {amount}. New balance: {self.balance}")
else:
print("Insufficient balance")
@classmethod
def set_interest_rate(cls, rate):
"""Class method to modify the interest rate"""
cls.interest_rate = rate
@staticmethod
def bank_info():
"""Static method: general information"""
print("Welcome to PyBank!")
# Usage
BankAccount.bank_info() # Static method
account1 = BankAccount("Alice", 1000)
account1.deposit(500) # Deposits 500
account1.withdraw(200) # Withdraws 200
print(BankAccount.interest_rate) # 0.02
BankAccount.set_interest_rate(0.03)
print(BankAccount.interest_rate) # 0.03