Maintenance

Site is under maintenance — quizzes are still available.

Go to quizzes
Python

When to Use __new__ vs __init__ in Python

Understand the difference between Python's __new__ and __init__ methods, when to use each, and avoid common pitfalls with clear examples.

July 2026 5 min read 2 views 0 hearts

When Python Constructors Confuse Even Seasoned Developers

If you've spent any time working with Python classes, you've probably used __init__ dozens of times without a second thought. It's the go-to method for setting up objects. But then someone mentions __new__, and suddenly things get fuzzy. What does it do? Why do we need both? And which one should you actually use?

Let me clear this up once and for all.

The Simple Truth

__init__ initializes an object after it exists. __new__ creates the object in the first place. Think of it this way: __new__ is the builder, __init__ is the interior decorator.

When you call MyClass(), Python first calls __new__ to create the instance, then calls __init__ to set it up. Here's what that looks like:

class Person:
    def __new__(cls, *args, **kwargs):
        print("Step 1: Creating the instance")
        instance = super().__new__(cls)
        return instance

    def __init__(self, name):
        print("Step 2: Initializing the instance")
        self.name = name

p = Person("PythonSkillset")
# Output:
# Step 1: Creating the instance
# Step 2: Initializing the instance

Notice __new__ gets the class as its first argument (cls), while __init__ gets the actual instance (self). That's because self doesn't exist yet when __new__ runs.

When You Actually Need __new__

Most Python developers go years using only __init__, and that's perfectly fine. __new__ is for special cases. Here are the main ones:

Singleton pattern - When you want a class that creates only one instance:

class DatabaseConnection:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            cls._instance = super().__new__(cls)
            print("Creating the one true connection")
        return cls._instance

conn1 = DatabaseConnection()
conn2 = DatabaseConnection()
print(conn1 is conn2)  # True - same object

Immutable types - When you're subclassing int, str, or tuple. These are created before __init__ runs, so you need __new__:

class PositiveInt(int):
    def __new__(cls, value):
        if value < 0:
            raise ValueError("Only positive numbers allowed")
        return super().__new__(cls, value)
    # Don't need __init__ here - int handles it

five = PositiveInt(5)    # Works
neg = PositiveInt(-3)    # Raises ValueError

Metaclass magic - When controlling class creation itself (advanced territory, but worth knowing exists).

The One Rule That Catches Everyone

Here's something that trips up even experienced Python developers: __init__ gets called automatically only if __new__ returns an instance of the class. If you return something else, __init__ is silently skipped.

class Tricky:
    def __new__(cls):
        return "I'm a string, not a Tricky object"

    def __init__(self):
        print("This never runs")

t = Tricky()
print(type(t))  # <class 'str'>

This is exactly why you should almost always call super().__new__() in your custom __new__ methods. Otherwise, you break the expected behavior.

Common Misconception Debunked

Some developers think __new__ is for complex initialization. It's not. __init__ handles that. __new__ is for instance creation control - deciding what type of object gets returned.

Think of it like ordering coffee: __new__ is deciding whether you get a cup or a mug, while __init__ is deciding if it's black or with sugar.

Practical Advice

For 95% of your Python code, stick with __init__. It's cleaner, simpler, and what everyone expects. Only reach for __new__ when:

  1. You're implementing singletons
  2. You're subclassing immutable types
  3. You're working with metaclasses
  4. You need to return a different object type than the class normally creates

PythonSkillset's own database wrapper libraries use __new__ sparingly - only for connection pooling where controlling instance creation matters. Everything else uses plain __init__.

The Bottom Line

__new__ and __init__ aren't competing alternatives. They serve different purposes in Python's object creation pipeline. Use __init__ by default, understand __new__ for those specialized scenarios, and you'll write cleaner, more predictable Python code.

Next time someone asks about the difference, you'll know exactly what to say: one builds the house, the other furnishes it.

Comments

Questions, corrections, and tips stay visible for everyone reading this page.

0 in thread

Join the discussion

Shown next to your comment.

Up to 4,000 characters

No comments yet

Be the first to leave a note — it helps the next reader.