Classes and Objects in Python: Syntax, Examples, and OOP Basics
Learn how Python classes and objects work: class syntax, __init__, instance vs class attributes, and how OOP questions appear in placement rounds.
A class in Python is a blueprint: it defines what attributes and methods every object created from it will carry.
That single sentence is the full model. The rest of this guide is an expansion of it, covering the syntax, the mechanics of object creation, and where these concepts appear in placement rounds.
What a class is and how to define one
The class keyword introduces a new class. By convention, class names use PascalCase (each word capitalised, no underscores). Attributes and methods go inside the class body, indented one level.
class Car:
brand = "Maruti" # class attribute
def drive(self):
print("Driving at 60 km/hr")
brand is a class attribute: defined at class level and shared by every Car object. drive is a method, a function bound to the class. The self parameter in the method signature refers to whichever object calls the method. You never pass self manually; Python injects it automatically.
At this point, Car is a class definition. No object exists yet. The Python tutorial on classes covers the complete syntax reference, including variable scoping rules and the distinction between class-level and instance-level names.
Creating objects with __init__
To create a Car object, call the class like a function:
maruti = Car()
audi = Car()
Python creates a new object and immediately calls the class’s __init__ method on it. __init__ (short for initialise) is where you set each object’s starting state.
class Car:
def __init__(self, brand, colour):
self.brand = brand # instance attribute
self.colour = colour # instance attribute
def describe(self):
print(f"{self.brand} in {self.colour}")
maruti = Car("Maruti", "White")
audi = Car("Audi", "Black")
maruti.describe() # Maruti in White
audi.describe() # Audi in Black
self.brand and self.colour are instance attributes. Each object gets its own copy. maruti.brand is “Maruti”; audi.brand is “Audi”. They live in separate memory.
__init__ is not called manually. Python calls it automatically when you write Car("Maruti", "White"). The first parameter to __init__ is always self; the remaining parameters are what you pass in.
Class attributes vs instance attributes
This distinction trips up students in written-round theory questions. Both kinds of attribute can be accessed via an object, which makes them look identical on the surface.
| Class attribute | Instance attribute | |
|---|---|---|
| Defined in | Class body, outside any method | __init__ via self.name = value |
| Shared across instances | Yes, all objects see the same value | No, each object has its own copy |
| Access | ClassName.attr or obj.attr | obj.attr only |
A common trap: if you assign a class attribute via a specific instance (a.wheels = 3), Python creates a new instance attribute on that object without touching the class attribute. Other objects still see the original class value.
class Car:
wheels = 4
a = Car()
b = Car()
a.wheels = 3 # creates instance attribute on a only
print(a.wheels) # 3 (instance attribute shadows class attribute)
print(b.wheels) # 4 (class attribute, unchanged)
print(Car.wheels) # 4 (class attribute, unchanged)
This shadowing behaviour surprises most students in their first pass through Python OOP. Written-round questions at TCS NQT and Wipro have tested exactly this edge case: “What does print(a.wheels) output after a.wheels = 3?”
Methods and how objects behave
Every function defined inside a class is a method. When called via an object, Python automatically passes that object as self. The Python data model documentation describes this as the descriptor protocol: obj.method(args) is equivalent to ClassName.method(obj, args) at the interpreter level.
class BankAccount:
def __init__(self, owner, balance):
self.owner = owner
self.balance = balance
def deposit(self, amount):
self.balance += amount
def show_balance(self):
print(f"{self.owner}: Rs.{self.balance}")
acc = BankAccount("Anjali", 10000)
acc.deposit(5000)
acc.show_balance() # Anjali: Rs.15000
deposit and show_balance each take self as their first parameter. When you call acc.deposit(5000), Python translates that to BankAccount.deposit(acc, 5000). You pass only 5000; Python adds acc silently.
The BankAccount example mirrors the class-design problems in Infosys InfyTQ coding assessments: model a real-world entity with state (attributes) and behaviour (methods), then trace what each method call produces.
OOP in placement rounds
Object-oriented concepts appear in three places in Indian placement assessments.
Written theory questions. The questions typically look like: “What is the purpose of __init__ in Python?”, “What is the difference between a class and an object?”, “What happens if you reassign a class attribute through an instance?” These appear in TCS NQT (foundation section), Infosys written rounds, and Wipro TalentNext.
Coding round. Students are asked to model a system using a class. Common prompts: a student record with name, roll number, and marks; a bank account with deposit and withdrawal methods; a shape class with area and perimeter methods. The BankAccount implementation above fits the bank account prompt without modification.
Technical interview. At product companies and mid-size tech firms, class and object mechanics are the starting point for deeper design questions. Interviewers move from “define a class” to “how would you design this system?” quickly. That shift requires understanding not just the syntax but the purpose of encapsulating state and behaviour together.
For the broader set of theory questions that appear alongside OOP in technical rounds, 20 most asked data structures interview questions covers arrays, trees, and hash tables in the same question-and-answer format.
Python coding practice, including string manipulation problems like palindrome checks, builds the same pattern-recognition that helps in timed placement assessments.
When placement prep moves past class syntax into design, abstract classes are the natural next step. Python’s abc module lets you define method contracts that every derived class must implement, enforcing the interface at instantiation time. The abstraction in Python guide covers abstract base classes and the @abstractmethod decorator with interview-ready code examples.
Applying classes beyond syntax exercises
Knowing class, __init__, and self is enough to model almost any structured entity in a program. A student record, a product catalogue entry, a transaction log: each becomes a class with attributes and methods that reflect its real-world behaviour.
The BankAccount structure from section four scales directly into AI application design. Systems that call language models wrap the API in a class with methods for prompting, parsing, and logging responses. TinkerLLM uses exactly this pattern in its build exercises: the ₹299 entry tier starts with the same class mechanics, applied to an LLM call handler rather than a bank account.
Primary sources
Frequently asked questions
What is the difference between a class and an object in Python?
A class is the definition, the blueprint. An object is a specific instance created from that class. You can create many objects from one class; each carries its own attribute values but shares the same method code.
What does self mean in a Python method?
self refers to the specific object the method is being called on. When you call account.deposit(500), Python passes account as self automatically. Inside the method, self.balance refers to that object's balance attribute.
Can a class exist without an __init__ method?
Yes. Python provides a default __init__ if you don't define one. The class can still create objects; those objects just won't have instance-specific attributes set at creation time unless you assign them manually afterward.
What is the difference between a class attribute and an instance attribute?
A class attribute is defined in the class body outside any method and is shared across all instances. An instance attribute is assigned inside __init__ using self.name = value; each object gets its own separate copy.
How do I add a new attribute to an object after it is created?
Assign directly: obj.new_attr = value. Python objects are dynamic; attributes can be added at any time. Most statically typed OOP languages such as Java or C++ do not allow this, so it surprises students encountering Python OOP for the first time.
Why do placement tests ask about OOP concepts?
OOP is the design foundation of most production codebases. Interviewers use class and object questions to check whether a candidate can reason about code structure and maintainability, not just isolated algorithms.
A self-paced playground for building with LLMs.
TinkerLLM is FACE Prep's sister property. A guided environment for shipping real LLM applications, the kind of project that earns a paragraph on your resume, not a line.
Try TinkerLLM (₹299 launch)