I stumbled upon a question yesterday that involved enumerating over an iterable type and yeilding descending indices accompanied by ascending items in the iterable.
In:
letters = ['a', 'b', 'c']
for i, letter in revenumerate(letters):
print('{}, {}'.format(i, letter))
Out:
2, a
1, b
0, c
Instead of writing a quick and reliable answer applying built-in reverse
twice, or simply i = len(letters) - i - 1
, I decided to try create a child class of enumerate
that redefines __iter__
and __next__
methods.
The code for my original working solution was as follows:
class revenumerate(enumerate):
def __init__(self, iterable, start=0):
self._len = len(iterable)
self._start = start
if isinstance(iterable, dict):
self._data = iterable.keys()
else:
self._data = iterable
def __iter__(self):
_i = self._len
for _item in self._data:
_i -= 1
_ind = _i + self._start
yield _ind, _item
def __next__(self):
_i, _item = super().__next__()
_ind = self._len + 2 * self._start - _i - 1
return _ind, _item
However, I now realize this code has redundancy as enumerate.__iter__
appears to yield the result of __next__
, makes sense. After deleting the redefined __iter__
I realized that self._data
was not being used anywhere, so I removed the last four lines from __init__
leaving me with the following code, which still provides the desired behavior.
class revenumerate(enumerate):
def __init__(self, iterable, start=0):
self._len = len(iterable)
self._start = start
def __next__(self):
_i, _item = super().__next__()
_ind = self._len + 2 * self._start - _i - 1
return _ind, _item
Now it appears that the iterable argument passed into revenumerate
is not for anything except determining the integer self._len
.
My question is - where is iterable
stored and how does super().__next__
access it?
A quick look at builtins.py
with the PyCharm debugger does not provide a lot of help in figuring this out (or so it seems to me at this stage), and I am not well traversed with the Python source code repository. My guess is something to do with the __new__
or __init__
method of parent class enumerate
, or it's parent object
.