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...')
CodePudding user response:
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;
}