When you create an instance of a class with MyClass(args) , the default instance creation sequence is as follows:
MyClass.__new__(args) is called to get a new "empty" instance. Callednew_instance.__init__(args) ( new_instance is the instance returned from the __new__ call as described above) to initialize the attributes of the new instance [1]new_instance returned as the result of MyClass(args)
From this it is clear that the call to MyClass.__new__ will not MyClass.__new__ when __init__ called, so you will get an uninitialized instance. It is equally clear that calling __init__ on __new__ also incorrect, since then MyClass(args) will call __init__ twice.
The source of your problem is the following:
I am trying to figure out what new instances of the Python class should look like when the creation process can be either through a constructor or using a new method
The creation process usually should not be performed using the __new__ method. __new__ is part of the protocol for creating a regular instance, so you should not expect it to call the entire protocol for you.
One (bad) solution would be to implement this protocol manually; instead:
def __getitem__(self, index): return self.__new__(type(self), self.data[index])
you may have:
def __getitem__(self, index): new_item = self.__new__(type(self), self.data[index]) new_item.__init__(self.data[index]) return new_item
But in fact, what you want to do is not confused with __new__ at all. By default, __new__ is appropriate for your case, and the default instance creation protocol is suitable for you, so you should not implement __new__ or call it directly.
You want to create a new instance of the class in the usual way by calling the class. If there is no inheritance, and you do not think it will ever be, just replace self.__new__(type(self), self.data[index]) with MyClass(self.data[index]) .
If you think that one day there may be subclasses of MyClass that would like to instantiate the subclass through slicing rather than MyClass , then you need to dynamically get the self class and call it. You already know how to do this because you used it in your program! type(self) will return the type (class) of self , which you can then call just like you would call it directly via MyClass : type(self)(self.data[index]) .
As an aside, the __new__ point is when you want to configure the process of getting a βnewβ empty class instance before initializing it. Almost all the time, this is completely unnecessary, and by default __new__ is fine.
You only need __new__ in two cases:
- You have an unusual distribution scheme in which you can return an existing instance instead of creating a truly new one (the only way to create a new instance is to delegate the final default implementation
__new__ anyway). - You implement a subclass of an immutable built-in type. Since immutable built-in types cannot be changed after creation (because they are immutable), they must be initialized as , they are created, and not then in
__init__ .
As a generalization of point (1), you can make __new__ return whatever you like (not necessarily an instance of the class) to make the class call behave in some arbitrarily bizarre way. It seems that this will almost always be more confusing than useful.
[1] I find the protocol a little more complicated; __init__ is only called for the value returned by __new__ if it is an instance of the class that was called to start the process. However, this is very unusual for this should not be.