new in Python (original) (raw)

Python is an **object-oriented programming language, where everything is an object. Python provides several special methods, known as magic methods or dunder methods (dunder means double underscores), which enable powerful and flexible object-oriented capabilities. These methods start and end with double underscores (e.g., __init__, __add__, __len__, __repr__, etc.). One such powerful magic method is **__new__, which plays an important role in instance creation.

What is __new__ in Python?

Whenever a class is instantiated, two methods are called:

Unlike **__init__, which is used for setting up an object after it has been created, **__new__ is responsible for creating and returning the new instance itself.

**Example:

Python `

class A: def new(cls): print("Creating instance") return super(A, cls).new(cls)

def __init__(self):
    print("Initializing instance")

A()

`

Output

Creating instance Initializing instance

**Explanation: __new__ method is called first to create an instance of class A and then returns the newly created instance. After that, the __init__ method initializes the instance.

**Syntax

class ClassName:

def __new__(cls, *args, **kwargs):

# Custom instance creation logic

instance = super(ClassName, cls).__new__(cls, *args, **kwargs)

return instance

**Parameters:

**Return Value:

Alternative method

Instances can be created in __new__ using either:

instance = super(ClassName, cls).__new__(cls, *args, **kwargs)

or

instance = object.__new__(cls, *args, **kwargs)

If both **__new__ and **__init__ exist in a class, **__new__ executes first. It determines whether __init__ should be executed by either returning an instance of the class or bypassing __init__ by returning an instance of another class.

Examples of __new__ method

**Example 1: What happens if __new__ does not return an instance?

Python `

class A: def new(cls): print("Creating instance")

def __init__(self):
    print("Initializing instance")

print(A())

`

Output

Creating instance None

**Explanation: __new__ method does not return an instance of the class. Since __new__ must return an instance, but it lacks a return statement, it implicitly returns None.

**Example 2: Returning a different type from __new__

Python `

class A: def new(cls): print("Creating instance") return "Hello, World!"

print(A())

`

Output

Creating instance Hello, World!

**Explanation : __new__ method should return a new object of **class A, but here it returns the string "Hello, World!". Because of this, Python does not create an instance of **A, so the __init__ method is never called. Instead, print(A()) simply prints "Hello, World!".

**Example 3: Returning an instances of another class

Python `

class GeeksforGeeks: def str(self): return "GeeksforGeeks Instance"

class Geek: def new(cls): return GeeksforGeeks()

def __init__(self):
    print("Inside init")

print(Geek())

`

Output

GeeksforGeeks Instance

**Explanation :__new__ method of Geek returns an instance of GeeksforGeeks instead of Geek, so the __init__ method is never called. When print(Geek()) is executed, it prints "GeeksforGeeks Instance" from the **__str__ method of GeeksforGeeks.

**Example 4: Returning values from **__new__ and __init__

Python `

class A(object): def new(cls): print("Creating instance") return "GeeksforGeeks"

class B(object): def init(self): print("Initializing instance") return "GeeksforGeeks"

print(A()) print(B())

`

**Output

Hangup (SIGHUP)
Traceback (most recent call last):
File "/home/guest/sandbox/Solution.py", line 12, in
print(B())
~^^
TypeError: init() should return None, not 'str'

**Explanation: In **class A, the **__new__ method prints "Creating instance" and returns the string "GeeksforGeeks", so the **__init__ method is never called. This results in "GeeksforGeeks" being printed. In class B, the __init__ method incorrectly tries to return a string, but since __init__ must return None, it raises a **TypeError.

When to use __new__

**__new__ is rarely overridden, but it is useful in specific scenarios, such as: