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:
- __new__ : Responsible for creating a new instance of the class.
- __init__ : Initializes the instance.
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()
OutputCreating 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:
- cls : The class itself.
- *args : Positional arguments passed to __new__ .
- **kwargs : Keyword arguments passed to __new__ .
Return Value:
- Must return an instance of the class (cls) or another class.
- If __new__ returns an object of another type, __init__ will not be called.
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())
OutputCreating 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())
OutputCreating 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())
OutputGeeksforGeeks 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 <module>
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:
- Implementing Singleton Pattern: Ensures only one instance of a class exists.
- Returning Cached Objects: Helps in memory optimization by reusing existing objects instead of creating new ones.
- Immutable Object Creation: Used in classes like str and tuple since they are immutable.
- Subclassing Immutable Types: When extending built-in immutable types like int, float or str.
Similar Reads
Python __init__ vs __new__
In Python, __init__ and __new__ are part of a group of special methods in Python commonly referred to as dunder methods or magic methods. The term "dunder" is short for "double underscore," reflecting the naming convention with double underscores at the beginning and end of the method names.Python _
3 min read
__init__ in Python
Prerequisites - Python Class and Objects, Self__init__ method in Python is used to initialize objects of a class. It is also called a constructor. It is like a default constructor in C++ and Java. Constructors are used to initialize the objectâs state.The task of constructors is to initialize (assig
5 min read
Namedtuple in Python
Python supports a type of container dictionary called "namedtuple()" present in the module "collections". In this article, we are going to see how to Create a NameTuple and operations on NamedTuple.What is NamedTuple in Python?In Python, NamedTuple is present inside the collections module. It provid
8 min read
Inheritance in Python
Inheritance is a fundamental concept in object-oriented programming (OOP) that allows a class (called a child or derived class) to inherit attributes and methods from another class (called a parent or base class). This promotes code reuse, modularity, and a hierarchical class structure. In this arti
7 min read
What's new in Python 3.9?
A new version of Python is coming! Soon, we'll be using it in our Python projects. As of 20/07/2020 Python 3.9 is in beta version(3.9.0b4) and will release the full version of Python 3.9 pretty soon. Enough of introduction. Let's get started and learn about the new features. 1. Dictionary merge and
3 min read
Iterators in Python
An iterator in Python is an object that holds a sequence of values and provide sequential traversal through a collection of items such as lists, tuples and dictionaries. . The Python iterators object is initialized using the iter() method. It uses the next() method for iteration.__iter__(): __iter__
3 min read
Name mangling in Python
In name mangling process any identifier with two leading underscore and one trailing underscore is textually replaced with _classname__identifier where classname is the name of the current class. It means that any identifier of the form __geek (at least two leading underscores or at most one trailin
3 min read
__call__ in Python
Python has a set of built-in methods and __call__ is one of them. The __call__ method enables Python programmers to write classes where the instances behave like functions and can be called like a function. When this method is defined, calling an object (obj(arg1, arg2)) automatically triggers obj._
4 min read
as Keyword - Python
as keyword in Python plays a important role in simplifying code, making it more readable and avoiding potential naming conflicts. It is mainly used to create aliases for modules, exceptions and file operations. This powerful feature reduces verbosity, helps in naming clarity and can be essential whe
3 min read
__getitem__() in Python
__getitem__() is a special method (also known as a dunder or magic method) in Python that allows us to access an element from an object using square brackets, similar to how we access items in a list, tuple, or dictionary. It is commonly used to retrieve items from containers or objects that support
3 min read