__init__ and __new__
Overview
When creating an object in Python, `__new__` is called first to allocate memory and return an uninitialized instance. `__init__` is then called on that instance to initialize its state. Most developers only use `__init__`. You only need `__new__` when you need to control the creation of a new instance. Common use cases include returning an existing instance for a Singleton, or subclassing immutable types like `tuple` or `str`. It is like building a house: `__new__` lays the foundation and frames the structure, while `__init__` paints the walls and moves the furniture in. class Sneaky: def __new__(cls): return 42 def __init__(self): print("Never runs!") obj = Sneaky() # obj is 42 If `__new__` returns something that is not an instance of `cls`, Python skips calling `__init__` entirely. This is a common trap when overriding object creation. class Singleton: _instance = None def __new__(cls): if not cls._instance: cls._instance = super().__new__(cls) return cls._instance def __init__(self): print("Init called!") a = Singleton() b = Singleton() # Prints "Init called!" again! Even if `__new__` returns an already-created instance, Python still automatically calls `__init__` on it every single time. This complicates initialization in some patterns, covered fully in `singleton-pattern`.
Understanding the two-step instantiation process allows you to implement advanced patterns like Singletons, flyweight objects, and custom metaclasses.
Where used: Django ORM model instantiation, Pydantic model creation, Standard library singletons
Why learn this
- Allows implementation of the Singleton pattern.
- Enables subclassing immutable types like `str` or `tuple`.
Code walkthrough
class Person:
def __new__(cls, name):
print('1. Creating instance')
return super().__new__(cls)
def __init__(self, name):
print('2. Initializing instance')
self.name = name
p = Person('Alice')
Focus: return super().__new__(cls)
Aha moment
class Singleton:
_instance = None
def __new__(cls):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance
a = Singleton()
b = Singleton()
print(a is b)
Prediction: What does this print?
Common guess: False
Because `__new__` intercepts the creation step, it can return an already-existing object. Here, it returns the same instance for both `a` and `b`, making `a is b` true.
Common mistakes
- Forgetting to return the instance in `__new__`: If `__new__` doesn't return an instance of the class, `__init__` is never called. Always return `super().__new__(cls)`.
- Trying to return a value from `__init__`: `__init__` must return `None`. It modifies the instance in-place. If you want to return a different object, do it in `__new__`.
Glossary
- Singleton
- A design pattern that ensures a class only ever has one single instance created, no matter how many times you try to instantiate it. Example: `db1 = DB(); db2 = DB(); assert db1 is db2` — both variables point to the same object.
- flyweight
- A design pattern that minimizes memory usage by sharing as much data as possible with other similar objects. Example: Python reuses the same integer object for small numbers like `1` rather than creating a new object each time.
Recall questions
- Which method is responsible for actually creating and returning a new instance in memory?
- If `__new__` does not return an instance of the current class, what happens to `__init__`?
- What is the primary reason you would override `__new__` instead of `__init__`?
Understanding checks
What will this code print when executed?
new init
Python first calls `__new__` which allocates the instance and returns it, and since the instance returned is of type `Custom`, Python immediately calls `__init__`.
What will this code print when executed?
new
Because `__new__` does not explicitly return the newly created instance, it implicitly returns `None`. Since it didn't return an instance of `MissingReturn`, `__init__` is never called.
Practice tasks
Subclassing float
The provided code subclasses `float` but doesn't change its behavior. Modify it by overriding `__new__` so that any value passed to `PositiveFloat` is converted to its absolute value before initialization.
Challenge
Implementing a basic Singleton
Implement a `DatabaseConnection` class using the Singleton pattern. It should have an `__init__` method that sets `self.connected = True` ONLY if the connection hasn't been established yet. Overriding `__new__` will let you ensure only one instance is ever created.
Continue learning
Next: Singleton pattern