Constructors in Python: __init__, Default, and Parameterised
How Python constructors work: __init__ syntax, default vs parameterised patterns, the mutable-default-argument pitfall, and placement assessment context.
__init__ is Python’s constructor: a method the interpreter calls automatically the moment a new object comes into existence.
That’s the complete mental model. Every detail in this guide (default vs parameterised, the mutable-default pitfall, __new__) is an expansion of that single idea.
What __init__ does (and what “constructor” means in Python)
In C++ and Java, the constructor is a method with the same name as the class. Python takes a different approach: every class has a method named __init__, and that is always the constructor regardless of the class name.
When you write emp = Employee("Priya", 45000), Python does two things in sequence:
- Allocates memory for a new object (handled by
__new__). - Calls
Employee.__init__(emp, "Priya", 45000)on that fresh object.
You never call __init__ directly. Python’s object-creation machinery invokes it. The Python tutorial on classes describes this as the class’s “initialisation method”, which is the accurate term: it does not create the object, it initialises it.
class Employee:
def __init__(self, name, salary):
self.name = name # instance attribute
self.salary = salary # instance attribute
emp = Employee("Priya", 45000)
print(emp.name) # Priya
print(emp.salary) # 45000
self is a reference to the object being initialised. It is always the first parameter. When you call Employee("Priya", 45000), Python passes the new object as self and routes "Priya" and 45000 to name and salary. You never pass self manually.
Default constructor vs parameterised constructor
Python constructors come in two practical forms.
Default constructor
A default constructor defines __init__ with only self. Every object created from the class gets the same starting values.
class Applicant:
def __init__(self):
self.status = "applied"
self.round = 1
a1 = Applicant()
a2 = Applicant()
print(a1.status) # applied
print(a2.round) # 1
Both a1 and a2 start at the same state. Useful when objects always begin with identical values before diverging through method calls.
Parameterised constructor
A parameterised constructor adds parameters after self. Each object is created with distinct values.
class Applicant:
def __init__(self, name, college, cgpa):
self.name = name
self.college = college
self.cgpa = cgpa
a1 = Applicant("Priya", "PSG Tech", 8.4)
a2 = Applicant("Arjun", "NIT Trichy", 7.9)
print(a1.name) # Priya
print(a2.cgpa) # 7.9
Each object now carries its own data. This is the form used in almost every real program and in most placement coding prompts (“model a student record”, “model a bank account”, “model an employee with name and salary”).
Default values in a parameterised constructor
Python allows default parameter values, giving you the flexibility of both forms in a single constructor.
class Applicant:
def __init__(self, name, cgpa=0.0):
self.name = name
self.cgpa = cgpa
a1 = Applicant("Priya", 8.4) # cgpa = 8.4
a2 = Applicant("Arjun") # cgpa = 0.0 (default)
This keeps the interface clean while still letting callers skip optional arguments.
The mutable-default-argument trap
The most common constructor bug in placement coding assessments involves mutable default arguments: lists, dicts, or sets passed as default values.
# BUGGY — do not use this pattern
class Applicant:
def __init__(self, name, skills=[]):
self.name = name
self.skills = skills
a1 = Applicant("Priya")
a2 = Applicant("Arjun")
a1.skills.append("Python")
print(a2.skills) # ['Python'] — not what you intended
Why does a2.skills contain “Python”? Because Python evaluates default argument values once, at function-definition time, not at each call. The empty list [] is created once and reused for every call that uses the default. a1.skills and a2.skills are the same list object.
The fix is to use None as the default and create the list inside the method body:
# CORRECT
class Applicant:
def __init__(self, name, skills=None):
self.name = name
self.skills = skills if skills is not None else []
a1 = Applicant("Priya")
a2 = Applicant("Arjun")
a1.skills.append("Python")
print(a2.skills) # [] — correct, separate list
This pattern (None sentinel, then assign inside the body) is the standard Python idiom. It works for any mutable type: lists, dicts, sets.
Written-round questions at mid-size tech companies test this exact scenario: they show the buggy version and ask what a2.skills prints. The answer surprises candidates who haven’t encountered the issue before.
A brief look at __new__
__init__ initialises an already-created object. __new__ is the step before: it allocates memory, creates the object, and returns it. Python then passes that object to __init__.
The Python data model documentation describes __new__ as a static method that takes the class as its first argument and returns a new instance of that class.
For almost every program you will write during placements or internships, __init__ is the only one you need. __new__ matters in two scenarios:
- Immutable subclasses.
int,str, andtupleare immutable; their value is set at creation time, which means you can’t change it in__init__. If you subclass them and need to customise the value, you do it in__new__. - Singleton pattern. A Singleton ensures only one instance ever exists.
__new__checks whether an instance already exists; if so, it returns the existing one instead of allocating a new one.
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
s1 = Singleton()
s2 = Singleton()
print(s1 is s2) # True — same object
Outside immutable subclassing and singletons, leave __new__ alone.
Where constructors appear in placement assessments
Constructor concepts appear in three layers of Indian placement rounds.
Written theory questions. Questions include: “What is the purpose of __init__ in Python?”, “What is the difference between a default constructor and a parameterised constructor?”, “What is the output of the following code?” These appear in TCS NQT foundation and advanced sections, Infosys InfyTQ assessments, and Wipro TalentNext qualifying tests.
Coding prompts. The standard prompt is to model a real-world entity. Examples:
- A student record with name, roll number, and a list of marks.
- A bank account with owner name and initial balance.
- A recruitment-tracker class with applicant name, test score, and current round.
Each of these uses a parameterised constructor. The marks and skills variants often introduce the mutable-default pitfall deliberately to see whether a candidate writes the correct None-sentinel pattern.
Technical interview. At product companies and mid-size tech firms, a class-design question often serves as the entry point to a broader system-design discussion. An interviewer who starts with “write a class for an employee record” expects to follow up with “how would you extend this for multiple departments?”
For the written-question format used alongside OOP in technical rounds, 20 most asked data structures interview questions covers arrays, trees, and linked lists in the same interview-Q format.
Practising Python string problems like palindrome checks builds the same timed-assessment pattern-recognition that helps in constructor and OOP coding rounds.
The Applicant class from the mutable-default section is not a toy example. In production AI applications, the same constructor pattern (__init__ with None sentinels for mutable fields) appears in every class that wraps an LLM call, stores conversation history, or buffers parsed responses. TinkerLLM builds on this pattern from the first exercise: the ₹299 entry tier starts with a simple class, then adds methods that call a language model, and the mutable-default pitfall is live code in the second session.
Primary sources
Frequently asked questions
What is __init__ in Python and why is it called a constructor?
__init__ is a special method Python calls automatically when a new object is created. It initialises the object's attributes, which is the defining job of a constructor in OOP. The name comes from 'initialise'; the double `__` wrapping marks it as a dunder (magic) method that Python invokes at a fixed lifecycle point.
What is the difference between a default constructor and a parameterised constructor?
A default constructor defines __init__ with only self as a parameter, so every object gets the same starting values. A parameterised constructor adds extra parameters, letting you pass different values at creation time — for example, Employee('Priya', 45000) vs Employee('Arjun', 38000).
What is the mutable default argument bug in Python constructors?
If you write def __init__(self, skills=[]), all instances share the same list object. Appending to it on one instance silently changes every other instance. Fix: use def __init__(self, skills=None) and set self.skills = skills if skills is not None else [] inside the method body.
What does __new__ do, and when should I override it?
__new__ allocates the object in memory and returns it before __init__ runs. In most programs you never need to override it. The common exception is the Singleton pattern, where __new__ checks whether an instance already exists before creating a new one.
Does Python have a destructor, and when would I use __del__?
Yes. __del__ is called when the object is garbage-collected. In practice, Python's garbage collector handles most cleanup automatically, so __del__ is rarely needed. Use context managers (with statements) for explicit resource cleanup such as file handles or database connections instead.
How do constructor questions appear in TCS NQT and Infosys rounds?
Written theory sections ask: 'What is the purpose of __init__ in Python?', 'What happens if a class has no __init__?', and 'What is the output of this code?' with a short class definition. Coding rounds at Infosys InfyTQ often ask students to model an entity (employee, account, student) as a class with parameterised constructor and methods.
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)