I would like to make a Python iterator class using __next__ that skips certain elements.
For example, here I have implemented a generator using yield and continue and I would like the iterator class below it to do exactly the same thing.
def generator_style(my_iter):
for i in my_iter:
if i < 999990:
continue
yield i
print(", ".join(str(s) for s in generator_style(range(1000000))))
# prints 999990, 999991, 999992, 999993, 999994, 999995, 999996, 999997, 999998, 999999
class iterator_style:
def __init__(self, my_iter):
self.my_iter = iter(my_iter)
def __iter__(self):
return self
def __next__(self):
i = next(self.my_iter)
if i < 999990:
# what do I do here??? I can't use continue
return next(self)
return i
print(", ".join(str(s) for s in iterator_style(range(1000000))))
# I want it to print 999990, 999991, 999992, 999993, 999994, 999995, 999996, 999997, 999998, 999999
Unfortunately, this version crashes due to
RecursionError: maximum recursion depth exceeded while calling a Python object
It works for smaller numbers though.
I cannot replace the return next(self) line with continue because:
continue
^
SyntaxError: 'continue' not properly in loop
You're correct that recursion has a lot of limitations for algorithms like this. Typically you would want to avoid deep recursion to avoid RecursionErrors. In this case you need to recursively call __next__ 999990 times to get your value.
To avoid this you can use a while-loop instead. Just keep calling next until you reach a value that meets your criteria.
def __next__(self):
while (i := next(self.my_iter)) < 999990:
pass
return i
Another way you could write it, if you find the assignment expression confusing:
def __next__(self):
while True:
i = next(self.my_iter)
if i < 999990:
continue
return i
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With