In Python's object-oriented programming, __new__ is a rarely used method compared to __init__. While __init__ is commonly mistaken for a constructor, it's actually an initializer. The true instance creation happens in __new__.
class Publication(object):
def __init__(self, name):
super(Publication, self).__init__()
self.name = name
# Create a publication instance
p = Publication('Python Cookbook')
print(p.name)
Key differences according to Python dcoumentation:
__new__is called before instance creation and must return the instance__init__is called after instance creation to initialize attributes
class Publication(object):
def __new__(cls, name):
print('__new__ called')
return super(Publication, cls).__new__(cls)
def __init__(self, name):
print('__init__ called')
super(Publication, self).__init__()
self.name = name
p = Publication('Python Cookbook')
print(p.name)
Output:
__new__ called
__init__ called
Python Cookbook
Practical applications of __new__:
1. Inheriting Immuatble Types
__new__ allows subclassing immutable types like str, int, or tuple.
2. Metaclass Implementation
In Django, __new__ can help access request objects in form validation:
class CustomForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request')
super(CustomForm, self).__init__(*args, **kwargs)
def clean(self):
# Access self.request here
pass
# In admin.py
class CustomAdmin(admin.ModelAdmin):
def get_form(self, request, *args, **kwargs):
class FormMetaClass(CustomForm):
def __new__(cls, *args, **kwargs):
kwargs['request'] = request
return CustomForm(*args, **kwargs)
return FormMetaClass