Subclassing String

We used init when we wanted to customize how a new instance of a class is created. new works very similarly.

The major difference between the two though is when you use them.
If you’re customizing a mutable data type like list, you override init.
If you’re customizing an immutable type, you use new.

We will try to make a subclass of ‘str’ that reverses a string at creation.

class ReveresedStr(str):
    def __new__(*args, **kwargs):
        self = str.__new__(*args, **kwargs)
        self = self[::-1]
        return self

ReversedStr
extends from the str class.

__new__
It doesn’t take self parameters, that’s because it is a classmethod. Unlike init, they operate on a class and not on an instance.

str.__new__(*args, **kwargs)
We used str instead of super() because it is unsafe to use super inside of new.

The advantage of using the super or str.new is create the instance exactly like we would with the extended type (i.e. str in our case), as the only difference we aim towards is a reversed sequence.

self
Just a variable. You don’t have to use self, but it is recommended.

More About new & init

Just because immutable types expect you to override new doesn’t mean you can’t use init on them. They still call the method but you can’t change the initialization of the object in them.

In every object creation, both the new and the init methods are run. The non-obvious behavior is the new calls init. This is why init methods do not include a return statement. The newly created and initialized object is returned by the newmethod. Think of the init method as merely sprucing up the newly create object with attribute values, etc.