Locked learning resources

Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Locked learning resources

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

Providing Custom Object Creators

To learn more about *args and **kwargs, you can check out the Real Python course Python args and kwargs: Demystified.

00:00 Providing Custom Object Creators. Typically, you’ll write a custom implementation of .__new__() only when you need to control the creation of a new instance at a low level. Now, if you need a custom implementation of this method, then you should follow a few steps. Firstly, create a new instance by calling super().__new__() with appropriate arguments.

00:24 Secondly, customize the new instance according to your specific needs. And thirdly, return the new instance to continue the instantiation process. With these three steps, you’ll be able to customize the instance creation step in the Python instantiation process.

00:42 On-screen is an example of how you can translate these steps into Python code.

00:54 This example provides a template implementation of .__new__(). As usual, .__new__() takes the current class as an argument that’s typically called cls. In the first line of .__new__(), you call the parent class’s .__new__() method to create a new instance and allocate memory for it.

01:11 To access the parent class’s .__new__() method, you use the super() function. This chain of calls takes you up to object.__new__(), which is the base implementation of .__new__() for all Python classes.

01:24 The built-in object class is the default base class of all Python classes. The next step is to customize your newly created instance. You can do whatever you need to do to customize the instance at hand.

01:39 Finally, in the third step, you need to return the new instance to continue the instantiation process with the initialization step. Note that you are using *args and **kwargs to make the method more flexible and maintainable by accepting any number of arguments. You should always define .__new__() with *args and **kwargs unless you have a good reason to follow a different pattern. To learn more about these, check out this Real Python course.

02:13 It’s important to note that object.__new__() itself only accepts a single argument, the class to instantiate. If you call object.__new__() with more arguments, then you’ll get a TypeError.

02:30 In this example, you hand over *args and **kwargs as additional arguments in the call to super.__new__(). The underlying object.__new__() accepts only the class as an argument, so you get a TypeError when you instantiate the class.

02:50 However, object.__new__() still accepts and passes over extra arguments to .__init__() if your class doesn’t override .__new__().

02:57 This can be seen in the following variation of SomeClass.

03:07 In this implementation of SomeClass, you don’t override .__new__(). The object creation is then delegated to object.__new__(), which now accepts the value and passes it over to SomeClass.__init__() to finalize the instantiation. Now you can create new instances of SomeClass, and as you can see, they’re fully initialized.

03:31 Now that you know the basics of writing your own implementations of .__new__(), you’re ready to dive into a few practical examples that feature some of the most common use cases of this method in Python programming. In the next section, you’ll start out by looking at how to subclass an immutable built-in type.

Avatar image for Fabio Alvarez

Fabio Alvarez on Sept. 29, 2022

I don’t understand the porpose of new.

Avatar image for odaihamza

odaihamza on Dec. 5, 2022

I came for clarity on super(), but now I have __new__ headache. I find C more easy to understand.

Avatar image for Leodanis Pozo Ramos

Leodanis Pozo Ramos RP Team on Dec. 6, 2022

Hey @odaihamaza, for clarity on super() check out: realpython.com/python-super/

Become a Member to join the conversation.