Section 1: Defining Classes
This is where you learn the syntax for creating a class, which is the blueprint for your objects.
-
Syntax: You use the
classkeyword, followed by a name (traditionally starting with a capital letter), and a colon. Everything belonging to the class is indented underneath.class Student: # Attributes and methods will go here pass # 'pass' is a placeholder; it means "do nothing" # We use it when a block is syntactically required but has no content yet. -
Attributes: These are the variables associated with a class. There are two types:
- Class Attributes: Shared by all objects (instances) of the class. Think of them as a "factory setting." You define them directly inside the class.
- Instance Attributes: Specific to each object. A student's name is unique to them. You define these inside a special method called
__init__.
-
Methods: These are the functions defined inside a class. They represent the behaviors or actions an object can perform.
Analogy: The blueprint for a car (Car class) might specify that all cars have 4 wheels (a class attribute). However, the color of each specific car (red, blue) is an instance attribute.
Section 2: The __init__() Method and self
This section covers two of the most important concepts when defining classes in Python.
The __init__() Method (The Constructor)
The __init__() method is a special method that Python calls automatically every time you create a new object from a class. Its job is to initialize the object's attributes (i.e., set their initial values).
- Syntax: It's always named
__init__(with double underscores on both sides). - Purpose: It acts as the constructor. When you create a
Studentobject,__init__runs to assign thename,roll_no, etc., to that specific object.
The self Parameter
self is arguably the most crucial—and initially confusing—concept here.
-
What it is:
selfis a special parameter that must be the first parameter of every method in a class, including__init__(). -
What it represents: It represents the instance of the object itself. When you call a method on an object (e.g.,
student1.show_details()), Python automatically passes thestudent1object as theselfargument. -
Analogy: Imagine you have two robot objects,
robot_Aandrobot_B, made from aRobotclass. The blueprint has a methodreport_status(self).- When you call
robot_A.report_status(), Python internally calls it asRobot.report_status(robot_A). Inside the method,selfrefers torobot_A. - When you call
robot_B.report_status(), Python internally calls it asRobot.report_status(robot_B). Inside the method,selfrefers torobot_B.
- When you call
self is how a method knows which object's data it should work with. You use self.attribute_name to access the instance's attributes.
Putting It Together: A Complete Class Definition
class Student:
# Class Attribute (shared by all students)
school_name = "ABC Public School"
# The constructor method to initialize instance attributes
def __init__(self, name, roll_no):
# Instance Attributes (unique to each student object)
self.name = name # 'self.name' belongs to the object
self.roll_no = roll_no
# A method (behavior)
def show_details(self):
print("Name:", self.name)
print("Roll No:", self.roll_no)
print("School:", self.school_name) # Can also be Student.school_name
Section 3: Creating and Using Objects (Instances)
Once you have the class (the blueprint), you can create objects from it. This process is called instantiation.
-
Creating an Object: You call the class name as if it were a function, passing the arguments required by the
__init__method (except forself, which Python handles).# Creating two different objects (instances) of the Student class student1 = Student("Rohan", 101) student2 = Student("Priya", 102) -
Accessing Attributes and Methods: You use the dot notation (
.) to access an object's attributes and call its methods.# Accessing attributes of student1 print(student1.name) # Output: Rohan # Calling a method on student2 student2.show_details() # Output: # Name: Priya # Roll No: 102 # School: ABC Public School
Section 4: Data Hiding and Built-in Attributes
Data Hiding (Private Members)
In OOP, you often want to prevent direct access to certain attributes from outside the class. Python doesn't have strict "private" members like some other languages, but it has a convention to indicate that an attribute should not be accessed directly.
- How it's done: You prefix the attribute name with two underscores (e.g.,
__password). - What Python does: This triggers a mechanism called name mangling. Python secretly renames the attribute to
_ClassName__attributeName. This makes it difficult (but not impossible) to access from outside. It serves as a strong warning to other programmers: "Don't touch this directly!"
Code Example:
class Account:
def __init__(self, balance):
self.__balance = balance # This is a "private" attribute
def show_balance(self):
print("Balance is:", self.__balance)
acc1 = Account(5000)
acc1.show_balance() # This works perfectly
# print(acc1.__balance) # This will cause an AttributeError!
Built-in Class Attributes
Every class in Python comes with some special, built-in attributes that provide information about the class.
__dict__: A dictionary containing the class's namespace (its attributes and methods).__doc__: The documentation string (docstring) of the class, if one was provided.__name__: The name of the class.__module__: The name of the module in which the class is defined.
class Dog:
"""This is a class to represent a dog."""
pass
print(Dog.__doc__) # Output: This is a class to represent a dog.
print(Dog.__name__) # Output: Dog
Section 5: Special Methods and Garbage Collection
Special Methods (__del__ and __str__)
__del__()(The Destructor): This method is called just before an object is destroyed or "garbage collected." It's used for cleanup tasks, like closing a file or a network connection that the object was using. You rarely need to write this yourself, as Python's memory management is mostly automatic.__str__(): This is a very useful method. It's called whenever you try to convert an object into a string, such as when you useprint(object)orstr(object). By default, printing an object gives you a weird memory address. By defining__str__, you can provide a friendly, human-readable string representation.
Code Example:
class Book:
def __init__(self, title, author):
self.title = title
self.author = author
def __str__(self):
return f"'{self.title}' by {self.author}" # Returns a formatted string
book1 = Book("The Jungle Book", "Rudyard Kipling")
print(book1) # Python automatically calls book1.__str__()
# Output: 'The Jungle Book' by Rudyard Kipling
Destroying Objects (Garbage Collection)
Python handles memory management automatically. It uses a system called reference counting.
- How it works: Python keeps track of how many variables are "pointing" to an object.
- When you create an object:
s1 = Student("Rohan", 101), the reference count for thisStudentobject becomes 1. - If you do
s2 = s1, now two variables point to the same object, and its reference count becomes 2. - When a variable is deleted (
del s1) or goes out of scope, the reference count decreases. - When the reference count of an object reaches zero, it means nothing is using it anymore. Python's garbage collector then automatically reclaims that memory, and the
__del__method is called just before this happens.
Arbind Singh
Teacher, Software developer
Innovative educator and tech enthusiast dedicated to empowering students through robotics, programming, and digital tools.

