I have some question about good practice. So say we have some class which we want to use as iterator. It class should returns first some header and then returns its blocks. I see two ways for this case:
- The first one is "classic". Return in iter methods self and put some logic in next method, like:
def __next(self): if not self._header_was_returned: self._header_was_returned = True return self._header if self._index >= self._count_blocks: raise StopIteration block = self._blocks[self._index] self._index += 1 return block - Or another one, in this case used less code, just implenet iter method:
def __iter__(self): yeild self._header for block in self._blocks: yield block Another case is create some class IteratorForMyBlockClass and implements ``_next``` method there, but it similar for the first case.
Updated:
From "Fluent Python" (Chapter 14). Main class is itarable (but not iterator). Main class should return some IteratorClass in __iter__ method. And in Iterator class I should put some logic:
class MainClass: def __init__(self, header, blocks): self._header = header self._blocks = blocks def __iter__(self): return MainClassIterator(self._header, self._blocks) class MainClassIterator: def __init__(self, header, blocks): self._header = header self._blocks = blocks self._index = 0 self._header_was_returned = False def __iter__(self): return self def __next__(self): if not self._header_was_returned: self._header_was_returned = True return self._header if self._index >= len(self._blocks): raise StopIteration block = self._blocks[self._index] self._index += 1 return block Is that a good solution?
selfin__iter__if that iterator is stateful (nearly all iterators are). If you would use multiple iterators concurrently, things will go wrong.__iter__, you are not implementing an iterator, you are implementing an iterable.