Home Blogs All Courses
python c OA ( Online Assessment ) Amazon Web Services (AWS) leetcode dsa algorithms java Machine learning
Get Referral
Login Sign Up

python › Python Classes and Objects

Python Classes and Objects: OOP Basics with __init__, self & Methods

phoolchandra  ·  Oct 23, 2026  · Published


Instagram has millions of users. Each user has a name, followers and posts, and each can follow, like and comment. Programmers don't write separate code for every user — they write one class called User and create millions of objects from it. This is the core of Object-Oriented Programming (OOP). In this blog you will master classes, objects, __init__, self, attributes, methods and more.

Watch the video first, then use this blog as your notes. Every section has runnable examples, and at the end you will find a "Predict the Output" quiz, practice challenges, a self-check list, interview questions and a quick summary.

How to use this blog: Open the Python shell (type python in your terminal) or any online Python editor and type every example yourself. Change the values, break the code and see what happens — that is how concepts really stick.

1. Class vs Object — The Blueprint Analogy

A class is a blueprint (a template). An object is a real thing built from that blueprint (an instance).

Class (blueprint)Objects (instances)
House map drawn by an architectYour house, your neighbour's house
Car designRiya's red Swift, Aman's white Creta
StudentRiya (roll 1), Aman (roll 2)
Defined onceCreated as many times as you need

Every object has:

  • Attributes (state / data) – what it has: name, colour, balance.
  • Methods (behaviour) – what it does: drive(), deposit(), study().

2. Creating Your First Class and Object

class Student:
    pass              # an empty class

s1 = Student()        # creating an object (instance)
s2 = Student()
print(type(s1))       # <class '__main__.Student'>
print(s1 == s2)       # False - two different objects

Naming convention: Class names use PascalCase: Student, BankAccount, ShoppingCart. Variables and methods use snake_case.

3. The __init__ Method (Constructor)

__init__ is a special method that runs automatically every time a new object is created. It is used to set the object's initial attributes.

class Student:
    def __init__(self, name, roll, marks):
        self.name = name          # instance attributes
        self.roll = roll
        self.marks = marks

s1 = Student("Riya", 1, 92)
s2 = Student("Aman", 2, 85)

print(s1.name, s1.marks)      # Riya 92
print(s2.name, s2.marks)      # Aman 85
Student("Riya", 1, 92)
   |
   v
1. Python creates an empty object
2. Calls __init__(self=<new object>, name="Riya", roll=1, marks=92)
3. Returns the ready object -> stored in s1

4. Understanding self

self refers to the current object — the one the method is working on. When you call s1.show(), Python actually calls Student.show(s1). So inside the method, self is s1.

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

    def greet(self):
        print("Hi, I am", self.name)

s1 = Student("Riya")
s1.greet()               # Hi, I am Riya
Student.greet(s1)        # exactly the same thing

Remember: self is just a naming convention (not a keyword), but always use it. Forgetting self in a method definition gives: TypeError: greet() takes 0 positional arguments but 1 was given.

5. Methods — Giving Objects Behaviour

class BankAccount:
    def __init__(self, owner, balance=0):
        self.owner = owner
        self.balance = balance

    def deposit(self, amount):
        self.balance += amount
        print(f"Deposited {amount}. Balance: {self.balance}")

    def withdraw(self, amount):
        if amount > self.balance:
            print("Insufficient balance!")
        else:
            self.balance -= amount
            print(f"Withdrew {amount}. Balance: {self.balance}")

acc = BankAccount("Riya", 1000)
acc.deposit(500)        # Deposited 500. Balance: 1500
acc.withdraw(2000)      # Insufficient balance!
acc.withdraw(300)       # Withdrew 300. Balance: 1200

6. Instance Attributes vs Class Attributes

class Dog:
    species = "Canis familiaris"   # class attribute - shared by ALL dogs
    count = 0

    def __init__(self, name):
        self.name = name           # instance attribute - unique to each dog
        Dog.count += 1

d1 = Dog("Tommy")
d2 = Dog("Bruno")
print(d1.species, d2.species)      # same for both
print(d1.name, d2.name)            # Tommy Bruno
print(Dog.count)                   # 2
Instance attributeClass attribute
Defined inside __init__ using self.Defined directly inside the class
Different for each objectShared by all objects
Accessed via obj.attrAccessed via ClassName.attr (or obj.attr)
Example: name, roll numberExample: school name, counter of objects

Trap: Writing d1.species = "X" does not change the class attribute — it creates a new instance attribute on d1 only. Dog.species and d2.species stay unchanged.

7. Instance, Class and Static Methods

class Student:
    school = "Coding Battle School"

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

    def introduce(self):                 # instance method - uses self
        return f"{self.name} studies at {self.school}"

    @classmethod
    def change_school(cls, new_name):    # class method - uses cls
        cls.school = new_name

    @staticmethod
    def is_adult(age):                   # static method - no self / cls
        return age >= 18

s = Student("Riya")
print(s.introduce())
Student.change_school("CB Academy")
print(s.introduce())                     # Riya studies at CB Academy
print(Student.is_adult(20))              # True
TypeFirst parameterCan accessUse for
Instance methodselfObject + class dataMost behaviour
Class method (@classmethod)clsClass dataFactory methods, changing class-level data
Static method (@staticmethod)NoneNothing automaticallyUtility functions related to the class

8. Special (Dunder) Methods: __str__ and __repr__

By default, printing an object shows something ugly like <__main__.Student object at 0x7f...>. Define __str__ to control it.

class Book:
    def __init__(self, title, price):
        self.title = title
        self.price = price

    def __str__(self):                    # for users (print)
        return f"{self.title} - Rs {self.price}"

    def __repr__(self):                   # for developers (debugging)
        return f"Book({self.title!r}, {self.price})"

b = Book("Python Basics", 299)
print(b)          # Python Basics - Rs 299
print([b])        # [Book('Python Basics', 299)]

9. Modifying and Deleting Attributes

s = Student("Riya")
s.name = "Riya Sharma"        # modify
s.age = 17                    # add a new attribute to this object only
print(hasattr(s, "age"))      # True
print(getattr(s, "name"))     # Riya Sharma
del s.age                     # delete
print(s.__dict__)             # {'name': 'Riya Sharma'}
print(isinstance(s, Student)) # True

10. Mini Project: Library Management

class Book:
    def __init__(self, title, author):
        self.title = title
        self.author = author
        self.is_issued = False

    def __str__(self):
        status = "Issued" if self.is_issued else "Available"
        return f"{self.title} by {self.author} [{status}]"


class Library:
    def __init__(self):
        self.books = []

    def add_book(self, book):
        self.books.append(book)

    def issue(self, title):
        for book in self.books:
            if book.title == title and not book.is_issued:
                book.is_issued = True
                return f"'{title}' issued successfully"
        return f"'{title}' is not available"

    def show(self):
        for book in self.books:
            print(book)


lib = Library()
lib.add_book(Book("Python Crash Course", "Eric Matthes"))
lib.add_book(Book("Clean Code", "Robert Martin"))
print(lib.issue("Clean Code"))
print(lib.issue("Clean Code"))
lib.show()
'Clean Code' issued successfully
'Clean Code' is not available
Python Crash Course by Eric Matthes [Available]
Clean Code by Robert Martin [Issued]

Quiz: Predict the Output

Don't run the code yet! Write your answers in a notebook, then check the Answers section at the end of this blog.

Q1. What is the output?

class A:
    x = 5
a = A()
b = A()
a.x = 10
print(A.x, a.x, b.x)

Q2. What is the output?

class Counter:
    count = 0
    def __init__(self):
        Counter.count += 1
Counter(); Counter(); Counter()
print(Counter.count)

Q3. What happens?

class Test:
    def hello():
        print("Hello")
Test().hello()

Q4. What is the output?

class P:
    def __init__(self, n):
        self.n = n
    def __str__(self):
        return "P" + str(self.n)
print(P(7))

Q5. What is the output?

class C:
    def __init__(self):
        self.items = []
c1, c2 = C(), C()
c1.items.append(1)
print(c2.items)

Q6. When is __init__ called?

Q7. Which decorator creates a method that receives the class as the first argument?

Practice Challenges

Solve these from easy to tricky:

  1. Create a class Rectangle with length and width, and methods area() and perimeter().
  2. Create a class Student with name and a list of marks, and a method average().
  3. Add a class attribute that counts how many Student objects have been created.
  4. Create a Car class with __str__ that prints like Red Swift (2024).
  5. Create a Temperature class with a static method that converts Celsius to Fahrenheit.
  6. Extend the Library project with a return_book(title) method.

Solutions for challenges 1, 2 and 3 are in the Answers section.

Self-Check: Can You Do This?

Tick off each skill once you are confident:

Frequently Asked Interview Questions

Q: What is the difference between a class and an object?
A class is a blueprint that defines attributes and methods; an object is a concrete instance created from the class.

Q: What is self in Python?
A reference to the current instance, passed automatically as the first argument of instance methods.

Q: Is __init__ a constructor?
It is the initializer. The object is actually created by __new__; __init__ then initialises it. In everyday terms it is called the constructor.

Q: Difference between __str__ and __repr__?
__str__ gives a user-friendly string (used by print); __repr__ gives an unambiguous developer representation (used in the shell and in lists).

Q: Can a class have multiple __init__ methods?
No — a later definition replaces the earlier one. Use default arguments or class methods as alternative constructors.

Summary

  • A class is a blueprint; an object is an instance of it.
  • __init__ initialises each new object; self is the current object.
  • Attributes store data; methods define behaviour.
  • Instance attributes are per object; class attributes are shared.
  • Use @classmethod for class-level logic and @staticmethod for utilities.
  • __str__ / __repr__ control how objects are displayed.

Quick Revision Cheat Sheet

ConceptSyntax / Key point
Define classclass Student:
Constructordef __init__(self, name):
Create objects = Student("Riya")
Access attributes.name
Call methods.greet()
Class method@classmethod def f(cls):
Static method@staticmethod def f():
Check instanceisinstance(s, Student)

Answers

Quiz answers

  1. 5 10 5 – a.x = 10 created an instance attribute on a only.
  2. 3
  3. TypeError – the method is missing self.
  4. P7
  5. [] – each object gets its own list in __init__.
  6. Automatically, every time a new object is created.
  7. @classmethod

Challenge solutions

# Challenge 1
class Rectangle:
    def __init__(self, length, width):
        self.length = length
        self.width = width

    def area(self):
        return self.length * self.width

    def perimeter(self):
        return 2 * (self.length + self.width)

r = Rectangle(5, 3)
print(r.area(), r.perimeter())        # 15 16

# Challenges 2 and 3
class Student:
    total_students = 0

    def __init__(self, name, marks):
        self.name = name
        self.marks = marks
        Student.total_students += 1

    def average(self):
        return sum(self.marks) / len(self.marks)

s1 = Student("Riya", [90, 85, 95])
s2 = Student("Aman", [70, 80, 75])
print(s1.average())                   # 90.0
print(Student.total_students)         # 2

Conclusion

You can now design your own classes and create objects — the foundation of OOP. Next, learn how to make reproducible random numbers with random.seed(), then continue to Encapsulation, Polymorphism and Inheritance.

If this blog helped you, watch the full video above, subscribe to the channel and share it with a friend who is learning Python. Happy coding!