Sitemap
Python in Plain English

New Python content every day. Follow to join our 3.5M+ monthly readers.

Python Object Creation: __new__ vs __init__

Learn the roles of __new__ and __init__ in Python object creation and initialization.

5 min readDec 5, 2024

--

Press enter or click to view image in full size
Connect with me on X

In Python, object-oriented programming revolves around creating and managing objects. Two special methods, __new__ and __init__, play vital roles in this process. However, their purposes are often confused by beginners and even some experienced developers.

While __init__ is widely used to initialize objects, __new__ is less commonly encountered, but equally important. Understanding their differences and how they work together is essential for mastering Python’s object model.

Today, in this article explores the roles of __new__ and __init__, their differences, and practical use cases where each shines.

Let’s dive in!

Hi, my name is CyCoderX. I write articles for everyone to enjoy, and I’d love your support by following me, clapping and highlighting parts of my article!

What is __new__?

The __new__ method in Python is responsible for creating a new instance of a class. It is called before __init__ and is typically used when you need to control how objects are created, such as in custom object creation scenarios.

Key Points about __new__:

  1. Purpose: Allocates memory and returns a new instance of the class.
  2. Called Before __init__: Without a properly created object from __new__, the __init__ method will not be called.
  3. Defined in the Base Class: By default, it is inherited from object.

Syntax of __new__:

class MyClass:
def __new__(cls, *args, **kwargs):
print("Creating a new instance of MyClass")
instance = super().__new__(cls)
return instance

Example of Using __new__:

class CustomClass:
def __new__(cls):
print("Creating a new CustomClass object")
instance = super().__new__(cls)
return instance

obj = CustomClass()

Output:

Creating a new CustomClass object

Why Use __new__?

You would typically use __new__ when:

  • Creating immutable objects like tuples or strings.
  • Implementing design patterns such as singletons.
  • Customizing object allocation behavior.

What is __init__?

The __init__ method in Python is responsible for initializing an instance of a class. It is called after __new__ and is typically used to set up the initial state of an object by assigning values to its attributes.

Key Points about __init__:

  1. Purpose: Prepares the created object by initializing attributes or performing setup tasks.
  2. Called After __new__: It operates on an already created instance.
  3. Does Not Return Anything: Unlike __new__, it does not allocate memory or return a new object.

Syntax of __init__:

class MyClass:
def __init__(self, name, age):
print("Initializing MyClass instance")
self.name = name
self.age = age

Example of Using __init__:

class Person:
def __init__(self, name, age):
print(f"Initializing Person: {name}, {age}")
self.name = name
self.age = age

person = Person("Alice", 30)

Output:

Initializing Person: Alice, 30

Why Use __init__?

You use __init__ for:

  • Setting initial values for attributes.
  • Performing setup tasks specific to the object.
  • Ensuring the object is in a consistent state before it’s used.

Connect with me on LinkedIn and X to stay ahead of industry trends and for more tips and tricks!

Key Differences Between __new__ and __init__

Here’s a breakdown of the differences between __new__ and __init__:

  • Purpose:
    __new__ is used to create a new instance of a class. It allocates memory and returns the instance. On the other hand, __init__ is used to initialize the attributes of an already created instance.
  • When They Are Called:
    __new__ is called first, during the object creation phase, while __init__ is called immediately afterward to perform initialization tasks.
  • Return Value:
    __new__ must return an instance of the class, either a new one or a previously existing one. In contrast, __init__ does not return anything.
  • Use Cases:
    You use __new__ when you need to customize how objects are created, such as implementing singletons or working with immutable objects. __init__, on the other hand, is used to set initial values for attributes or perform object-specific setup tasks.
  • Customization:
    __new__ is typically overridden when subclassing immutable types like tuple or str, while __init__ is defined in most classes to configure instance-specific details.

When to Use __new__ Over __init__

Although __init__ is more commonly used, there are specific scenarios where __new__ is necessary:

  • Immutable Objects:
    Since immutable objects like strings and tuples cannot be modified after they are created, you must use __new__ to customize their creation.

Example:

class CustomTuple(tuple):
def __new__(cls, iterable):
print("Creating a CustomTuple")
return super().__new__(cls, iterable)

obj = CustomTuple([1, 2, 3])
print(obj) # Output: (1, 2, 3)
  • Singleton Pattern:
    To ensure that only one instance of a class is created, you can use __new__.

Example:

class Singleton:
_instance = None

def __new__(cls, *args, **kwargs):
if cls._instance is None:
cls._instance = super().__new__(cls)
return cls._instance

obj1 = Singleton()
obj2 = Singleton()
print(obj1 is obj2) # Output: True
  • Custom Object Creation:
    If you need to modify the instance creation process, such as returning a cached instance or modifying class attributes, __new__ is the method to override.

Practical Examples Comparing __new__ and __init__

Example 1: Customizing Object Creation with __new__

In this example, we use __new__ to modify the creation process:

class PositiveInteger(int):
def __new__(cls, value):
if value < 0:
raise ValueError("Value must be positive")
return super().__new__(cls, value)

num = PositiveInteger(5)
print(num) # Output: 5

# num = PositiveInteger(-5) # Raises ValueError

Here, __new__ ensures that only positive integers are created, rejecting negative values during the object creation phase.

Example 2: Initializing Object Attributes with __init__

In this example, we use __init__ to set up instance-specific attributes:

class Person:
def __init__(self, name, age):
self.name = name
self.age = age

person = Person("Alice", 30)
print(person.name) # Output: Alice
print(person.age) # Output: 30

__init__ is used to initialize the attributes name and age for each instance of the Person class.

Conclusion

In Python, __new__ and __init__ serve distinct but complementary roles in object-oriented programming. __new__ is responsible for creating new instances of a class, while __init__ initializes these instances with specific values or configurations.

Join Medium for free to get updates from this writer.

Use __new__ when you need to customize the object creation process, such as working with immutable objects or implementing design patterns like singletons. For most everyday scenarios, __init__ suffices to set up instance-specific attributes and perform initialization tasks.

Understanding the differences between these methods allows you to leverage Python’s object model effectively and write more powerful, flexible code.

Final Words:

Thank you for taking the time to read my article. Article first published on Medium by CyCoderX.

Hi, I’m CyCoderX! An engineer passionate about sharing knowledge, I write articles about Python, SQL, Data Science, Data Engineering and more!

Please consider supporting me by:

  1. Clapping 50 times for this story
  2. Leaving a comment telling me your thoughts
  3. Highlighting your favorite part of the story

Socials

In Plain English 🚀

Thank you for being a part of the In Plain English community! Before you go:

--

--

CyCoderX
CyCoderX

Written by CyCoderX

Machine Learning & Data Engineer | Data Science | Python & SQL | AI | Software Developer | Azure & AWS Cloud Specialist | Blogger simplifying Big Data & Trends

Python in Plain English
Python in Plain English

Published in Python in Plain English

New Python content every day. Follow to join our 3.5M+ monthly readers.