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.