Logo OnlineCBT
PYTHON Tutorial
PYTHON · LESSON 32

Classes, Objects and Constructors

Model state and behaviour with classes and instances.

Level: Beginner to Advanced
Duration: ~60 Mins Deep-Dive
Updated: 26 Jul 2026

Lesson 32: Classes, Objects and Constructors

1. Introduction to Object-Oriented Programming (OOP)

Welcome to Module 4 of our Python Mastery Series: Object-Oriented Programming (OOP) in Depth! Up to this point, our code has been primarily procedural and functional—organizing logic into sequences of instructions, loops, conditionals, and independent utility functions that manipulate built-in primitives or collection data structures.

As applications scale to enterprise levels (like managing millions of customer user sessions, modeling complex banking accounts, or engineering game engines), procedural code can become fragmented. Data state and the functions that manipulate that data remain separated, leading to scope pollution and maintenance challenges.

Object-Oriented Programming is a software paradigm that unifies data attributes and behavior methods into cohesive, self-contained entities known as Objects, constructed according to formal blueprints called Classes.


2. Fundamental Concepts: Classes vs Objects

1. What is a Class?

A Class is a user-defined prototype or architectural blueprint. It defines the structure (attributes/variables) and actions (methods/functions) that all objects created from it will possess. A class creates a new custom data type in Python's memory space.

2. What is an Object (Instance)?

An Object (or instance) is a concrete realization of a class allocated in Python Heap memory. If Car is a class blueprint, then your red Tesla parked in the driveway is an object instance instantiated from that class.

  • Memory Status
  • Logical structure definition stored once in code memory.
  • Physical entity allocated in Heap memory with its own memory address (`id()`).
  • Analogy
  • Architectural blueprint for a house.
  • The physical house built on a specific street plot.
  • Python Syntax
  • Declared using class ClassName:
  • Instantiated calling obj = ClassName()
OOP Conceptual Dimension Class (Blueprint) Object (Instance)

3. Mechanics of Class Definition and the `self` Parameter

1. Class Header Declaration

In Python, classes are declared using the class keyword followed by the class identifier in PascalCase (e.g., BankAccount, UserProfile), following PEP 8 naming standards.

2. Demystifying the `self` Parameter

Every instance method inside a Python class MUST accept an explicit first parameter, conventionally named self.

How `self` Works Under the Hood: The self variable is an explicit reference to the current specific object instance invoking the method. When you call account.deposit(100), Python automatically translates the statement behind the scenes to: BankAccount.deposit(account, 100)! The active instance reference is passed into self automatically.
CLASS_DECLARATION_BASIC.PY
class BasicUser:
    """A minimal class representing a user entity."""
    pass

# Instantiating objects (calling the class constructor)
user_1 = BasicUser()
user_2 = BasicUser()

print("=== Class Type and Memory Instance Inspection ===")
print("Type of BasicUser Class :", type(BasicUser))
print("Instance user_1 Type    :", type(user_1))
print("Instance user_1 Memory ID:", id(user_1))
print("Instance user_2 Memory ID:", id(user_2))
print("Are Instance IDs Unique? :", id(user_1) != id(user_2))
OUTPUT
=== Class Type and Memory Instance Inspection ===
Type of BasicUser Class : 
Instance user_1 Type    : 
Instance user_1 Memory ID: 140239482910224
Instance user_2 Memory ID: 140239482911856
Are Instance IDs Unique? : True

4. The Constructor Method (`__init__`) and Instance Attributes

When an object is instantiated from a class, Python automatically invokes a special dunder method: __init__(), formally known as the Constructor Initializer.

1. Attribute Binding in `__init__`

The __init__ method initializes the starting state of an object by binding incoming arguments to instance variables attached to self (e.g., self.attribute_name = argument_value).

CONSTRUCTOR_INIT_DEMO.PY
class BankAccount:
    """Models a financial bank account entity with balance state and methods."""
    
    def __init__(self, account_number: str, owner_name: str, initial_balance: float = 0.0):
        # Binding parameters to instance attributes attached to self
        self.account_number = account_number
        self.owner_name = owner_name
        self.balance = initial_balance
        print(f"[CONSTRUCTOR] Account #{self.account_number} created for '{self.owner_name}'.")

    def display_statement(self):
        """Instance method accessing self instance attributes."""
        print(f"Account: {self.account_number} | Owner: {self.owner_name:<12} | Balance: ${self.balance:,.2f}")

# Instantiating objects with custom initialization state
acc_a = BankAccount("ACC_1001", "Alice Smith", 5000.0)
acc_b = BankAccount("ACC_1002", "Bob Jones", 1200.0)

print("\n--- Displaying Account Statements ---")
acc_a.display_statement()
acc_b.display_statement()
OUTPUT
[CONSTRUCTOR] Account #ACC_1001 created for 'Alice Smith'.
[CONSTRUCTOR] Account #ACC_1002 created for 'Bob Jones'.

--- Displaying Account Statements ---
Account: ACC_1001 | Owner: Alice Smith  | Balance: $5,000.00
Account: ACC_1002 | Owner: Bob Jones    | Balance: $1,200.00

5. Instance Attributes vs Class Attributes

In Object-Oriented Python, attributes exist at two distinct architectural levels:

1. Instance Attributes (`self.attr`)

Variables defined inside methods (usually __init__) using self. Every object instance maintains its own completely independent copy of instance attributes in its personal __dict__ memory space.

2. Class Attributes

Variables declared directly inside the class .tech-lesson-content, outside any methods. Class attributes are shared globally across ALL object instances instantiated from that class!

The Mutation Shadowing Pitfall: Modifying a class attribute using an instance pointer (e.g., instance.class_attr = 99) does NOT update the shared class variable! Instead, it creates a new **Instance Attribute** on that specific object that "shadows" (masks) the class variable! To mutate a class attribute globally, access it via the Class name directly: ClassName.class_attr = 99.
INSTANCE_VS_CLASS_ATTRIBUTES.PY
class Employee:
    # Class Attribute (Shared globally across all instances)
    COMPANY_NAME = "Apex Global Tech"
    total_employee_count = 0

    def __init__(self, emp_id: int, name: str):
        # Instance Attributes (Unique per object)
        self.emp_id = emp_id
        self.name = name
        
        # Increment shared class counter via Class Name
        Employee.total_employee_count += 1

# Instantiating multiple employees
e1 = Employee(101, "Alice")
e2 = Employee(102, "Bob")

print(f"Employee 1 Company: {e1.COMPANY_NAME} | Name: {e1.name}")
print(f"Employee 2 Company: {e2.COMPANY_NAME} | Name: {e2.name}")
print(f"Total Active Staff: {Employee.total_employee_count}")

# Demonstrating Global Mutation via Class Name
Employee.COMPANY_NAME = "Apex International Solutions"
print("\n--- After Mutating Employee.COMPANY_NAME globally ---")
print(f"Employee 1 Updated Company: {e1.COMPANY_NAME}")
print(f"Employee 2 Updated Company: {e2.COMPANY_NAME}")
OUTPUT
Employee 1 Company: Apex Global Tech | Name: Alice
Employee 2 Company: Apex Global Tech | Name: Bob
Total Active Staff: 2

--- After Mutating Employee.COMPANY_NAME globally ---
Employee 1 Updated Company: Apex International Solutions
Employee 2 Updated Company: Apex International Solutions

6. Integrating Class Instances with `match-case` Structural Pattern Matching

Python 3.10+ Class Pattern Matching allows inspecting custom class instances inside match-case statements directly, matching on instance types, extracting attributes, and applying conditional guards.

MATCH_CASE_CLASS_PATTERN.PY
class Order:
    def __init__(self, order_id: str, total_amount: float, customer_tier: str):
        self.order_id = order_id
        self.total_amount = total_amount
        self.customer_tier = customer_tier

def process_fulfillment_order(order_obj: object):
    """
    Routes custom class instance objects using Class Pattern Matching.
    Demonstrates inspecting instance attributes dynamically.
    """
    match order_obj:
        case Order(customer_tier="GOLD", total_amount=amt) if amt >= 1000.0:
            discount = amt * 0.20
            return f"VIP FULFILLMENT: 20% Tier Discount Applied (-${discount:.2f}). Net: ${amt - discount:.2f}"
            
        case Order(customer_tier="GOLD" | "SILVER", total_amount=amt):
            discount = amt * 0.10
            return f"STANDARD MEMBER: 10% Discount Applied (-${discount:.2f}). Net: ${amt - discount:.2f}"
            
        case Order(order_id=oid, total_amount=amt):
            return f"REGULAR PROCESSING: Full Amount Charged (${amt:.2f}) for Order #{oid}"
            
        case _:
            return "ERROR: Provided object is not a valid Order instance."

# Testing Class Instance Pattern Dispatcher
order_1 = Order("ORD_901", 1500.0, "GOLD")
order_2 = Order("ORD_902", 300.0, "SILVER")
order_3 = Order("ORD_903", 100.0, "REGULAR")

print(process_fulfillment_order(order_1))
print(process_fulfillment_order(order_2))
print(process_fulfillment_order(order_3))
OUTPUT
VIP FULFILLMENT: 20% Tier Discount Applied (-$300.00). Net: $1200.00
STANDARD MEMBER: 10% Discount Applied (-$30.00). Net: $270.00
REGULAR PROCESSING: Full Amount Charged ($100.00) for Order #ORD_903

7. Frequently Asked Interview Questions with Answers

Q1: What is the technical difference between a Class and an Object in Python?
Answer: A Class is a user-defined blueprint defining structural data fields and behavioral methods. An Object is a concrete memory instance instantiated from that class, possessing its own unique Heap memory address (`id()`) and instance dictionary (`__dict__`).
Q2: What is the role of the `self` parameter in Python instance methods?
Answer: self is an explicit reference pointing to the active instance invoking the method. It allows methods to access, modify, and bind instance-specific attributes (e.g., self.name) inside instance memory space.
Q3: How does the `__init__()` method work, and is it a true object allocator?
Answer: __init__() is an **initializer method**, NOT the raw object allocator. In Python, object allocation is handled first by __new__(), which creates the raw memory object and passes it to __init__() as self to bind instance attributes.
Q4: What is the difference between Instance Attributes and Class Attributes?
Answer: Instance attributes are defined inside methods using self and are unique to each instance object. Class attributes are declared directly inside the class body outside methods and are shared globally across all instances of that class.
Q5: How does Structural Pattern Matching (`match-case`) evaluate custom class instances?
Answer: Class pattern matching checks whether an object is an instance of a target class (e.g., case Order(...)) and inspects its internal instance attributes directly, matching specific values or binding them to local variables.

8. Homework & Practical Assignments

Task 1: Inventory Item Class with Instance Methods

Create a script named inventory_class_task.py inside your lesson_32 folder:

  • Define a class ProductItem with a constructor __init__(self, product_id, title, price, quantity).
  • Add an instance method calculate_total_value(self) -> float returning price * quantity.
  • Add an instance method restock(self, amount: int) that increments quantity.
  • Instantiate 2 product objects, perform restock operations, and print formatted statements using f-strings.

Task 2: Class Pattern Matching User Tier Evaluator

Create a script named class_pattern_task.py:

  • Define class UserProfile(username, credit_score, account_age_months).
  • Write function evaluate_credit_tier(user_obj) using match-case Class Pattern Matching:
    • case UserProfile(credit_score=score) if score >= 750 → Return "PRIME_TIER_APPROVED".
    • case UserProfile(credit_score=score, account_age_months=months) if score >= 650 and months >= 12 → Return "STANDARD_TIER_APPROVED".
    • case UserProfile() → Return "CREDIT_TIER_REJECTED".
  • Test function with 3 user objects and print results.

Task 3: Master Review Capstone Project — Object-Oriented Enterprise ERP System (`oop_enterprise_os.py`)

Create a script named oop_enterprise_os.py inside your lesson_32 folder. This assignment tests and integrates **ALL concepts learned across Lessons 1 through 32**.

Project Architectural Requirements Specification:

  1. Object-Oriented Architecture (Lesson 32):
    • Define core domain classes: Customer(customer_id, name, email, tier), InventoryItem(item_id, title, price, stock), and Transaction(tx_id, customer_obj, item_obj, qty).
    • Use __init__ constructors to bind instance attributes and track global counters via class attributes (e.g., Transaction.total_tx_count).
  2. Observability & Diagnostics (Lesson 31):
    • Configure a logging FileHandler writing diagnostic logs to erp_system.log.
    • Add internal developer assertions (assert) inside class methods to check state invariants (e.g., price > 0).
  3. Context Managers & Fault Tolerance (Lessons 29-30):
    • Build a custom context manager DatabaseSession(db_path) that manages JSON persistence files safely.
    • Define custom exceptions: ERPError(Exception), OutOfStockError(ERPError). Wrap transactions in 4-block try-except-else-finally suites.
  4. CSV & JSON Persistence Layer (Lessons 27-28):
    • Maintain a storage directory erp_vault/ using pathlib.Path.
    • Persist object dictionaries to inventory.json and export sales reports to sales_audit.csv.
  5. Nested Collections, Comprehensions & Data Structures (Lessons 21-26):
    • Maintain in-memory registry dictionaries mapping IDs to Class Instances.
    • Use List and Dictionary Comprehensions to transform instance collections dynamically.
  6. Advanced Function Parameters & Scope (Lessons 15-17):
    • Structure logic into modular functions with type hints, docstrings, early return Guard Clauses, and *args / **kwargs logging.
  7. Indefinite & Definite Loops (Lessons 13-14):
    • Run the main application inside a continuous while True menu loop.
    • Iterate through output reports using for loops with enumerate() and .items().
  8. Pattern Matching CLI Dispatcher (Lesson 12):
    • Process user CLI command tokens inside a match-case block:
      • case ["ADD_ITEM", item_id, title, price_str, stock_str] → Instantiate InventoryItem object and save to registry.
      • case ["BUY", cid, item_id, qty_str] → Fetch objects, check stock, raise OutOfStockError if insufficient, and execute sale inside DatabaseSession.
      • case ["AUDIT", "OBJECTS"] → Inspect object instances using Class Pattern Matching.
      • case ["EXIT" | "QUIT"] → Terminate session safely using a sentinel flag.
      • case _ → Output command error message.
  9. Conditionals, Formatting & Foundations (Lessons 1-11):
    • Sanitize all string inputs using .strip() and .upper().
    • Format tabular reports using f-strings with field width alignment specifiers (:<15, :>10) and currency formatting (:,.2f).

9. File & Workspace Directory Structure

Standard Course Workspace Layout:

Ensure all exercise files are stored inside their corresponding lesson directories:

python_mastery_course/
│
├── lesson_01/ ... lesson_31/
│
└── lesson_32/
    ├── class_declaration_basic.py
    ├── constructor_init_demo.py
    ├── instance_vs_class_attributes.py
    ├── match_case_class_pattern.py
    ├── inventory_class_task.py     <-- (Task 1)
    ├── class_pattern_task.py       <-- (Task 2)
    └── oop_enterprise_os.py        <-- (Task 3: Master Review Capstone)
        

10. What We Will Learn Next

Next Up: Lesson 33 — Instance, Class and Static Methods

Now that you master defining basic classes, constructors, and instantiating objects, we will explore method categorization in Python OOP!

In the next lesson, we will cover:

  • Understanding the three distinct method types in Python classes.
  • Standard Instance Methods bound to self.
  • Class-level factory methods using the `@classmethod` decorator and cls parameter.
  • Independent utility functions using the `@staticmethod` decorator.
  • Designing clean object creation factories and utility namespaces.

📝 Live Lesson Practice

HTML/CSS JavaScript Python C++ C PHP
⌨️ Practice Inputs (लाइव इनपुट भरें) (खाली होने पर RED, भरने पर GREEN underline)
💻 Code Editor (Monaco VS Code Engine)
👀 Live Preview
Address Contact

+91 7877547686

E-mail

onlinecbtportal@gmail.com

Helpline Number

+91 7877547686


Click To Download
Get it on Google Play

ऐप डाउनलोड करने
के लिए Google Play पर
उपलब्ध है

WhatsApp Chat