On Sat, May 9, 2020 at 7:10 PM Steven D'Aprano firstname.lastname@example.org wrote:
On Thu, May 07, 2020 at 11:12:28PM +0900, Stephen J. Turnbull wrote:
So of course zip can be said to be used like a class. Its instances are constructed by calling it, the most common (only in practice?) method call is .__iter__, it's invariably called implicitly in a for statement, and usually the instance is ephemeral (ie, discarded when the for statement is exited). But it needn't be. Like any iterator, if it's not exhausted in one iteration context, you can continue it later. Or explicitly call next on it.
In CPython 3.x, zip is a class. In 2.x it was a function returning a list. I don't know why it's a class now -- possibly something to do with the C implementation? -- but that's not part of the public API, and I would not expect that to be a language guarantee. The API is only that it returns an iterator, it doesn't have to be any specific class.
If zip were implemented in pure Python, it would probably be a generator, something like this:
def zip(a, b): while True: yield(next(a), next(b))
only better :-)
def zip(*iters): iters = [iter(i) for i in iters] try: while True: yield tuple(next(i) for i in iters) except StopIteration: pass
But ultimately, a generator function is very similar to a class with a __next__ method. When you call it, you get back a state object that you can ping for the next value. That's really all that matters. I think the C implementations tend to be classes but the Python ones tend to be generators - possibly because a generator function is way easier to write in Python, but maybe the advantage isn't as strong in C.
If it's going to have additional constructors, it makes good sense for it to be a class with classmethods. But again, either way WILL work just fine.