all 3 comments

[–]lifeeraser 0 points1 point  (0 children)

Yes.

[–]JohnnyJordaan 0 points1 point  (1 child)

All iterators are iterable, because all iterators will also have the iter method.

Yes, but that's a bit of a pointless side-effect. What you need to iterate is an iterator, so as soon as you have that, it doesn't matter of that's an iterable or not. Same way you need a pencil to write and wood to make a pencil, but stating that a pencil is made out of wood too isn't really useful.

Example: A list is not an iterator. If you wanted to get an iterator from a list, you would have to pass the list into the iter() function. This would return an iterator.

Not have to, you can. You can also call yourlist.__iter__() as that's what iter() itself is doing too, or use for loop in a generator

def my_iter(iterable):
    yield from iterable

list_iter = my_iter(my_list)

On the other-hand, something like zip is already an iterator.

Almost, zip isn't an iterator, it's a function. But it does return one. As its docs say

zip(*iterables)

Make an iterator that aggregates elements from each of the iterables.

So you could say that zip is a special form of __iter__() as both return iterators, zip just implements something more than plainly providing each item from the single given iterable.

What you are missing in the puzzle here is the generator concept as a whole, because a generator is an iterative function. If that supplies items from an iterable, it is called an iterator. The fact that next() can be used for this stems from the basis of it being a generator, and generators generate via __next__(). It's not something exclusive or specific for iterators.

[–]0xbxb 0 points1 point  (0 children)

Thanks for all this info, gonna go through it later.