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

Unlock This Lesson

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

Unlock This Lesson

Hint: You can adjust the default video playback speed in your account settings.
Hint: You can set the default subtitles language in your account settings.
Sorry! Looks like there’s an issue with video playback 🙁 This might be due to a temporary outage or because of a configuration issue with your browser. Please see our video player troubleshooting guide to resolve the issue.

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.

Become a Member to join the conversation.