Consider the code below. I am trying to subclass the builtin enumerate so that it prints a line for every turn of the for loop. The code seems to be working, which is surprising, because I have never called super().__init__(x). So, what is happening here? Who is initializing the base class enumerate the right way? Is there some magic from the __new__ method happening here?
class myenum(enumerate):
def __init__(self,x):
self.x_ = x
self.len_ = len(x)
def __next__(self):
out = super().__next__()
print(f'Doing {out[0]} of {self.len_}')
return out
for ictr, key in myenum(['a','b','c','d','e']):
print('Working...')
>Solution :
The __init__ method is always optional. All initialization of an instance can always be done purely in the __new__ method, which is the case for the enumerate class, whose __new__ method is defined here in the enum_new_impl function, where you can see that the iterable argument is stored as the attribute en_sit of the returning object en, of the struct type enumobject:
static PyObject *
enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start)
{
enumobject *en;
...
en->en_sit = PyObject_GetIter(iterable);
...
return (PyObject *)en;
}