An iterable is anything you can loop over (a list, string, dict); an iterator is the object that does the actual iteration, producing values one at a time and tracking its position. The distinction underlies how for loops work in Python.
The two protocols
Iterable → has __iter__() → returns an iterator
Iterator → has __next__() → returns the next value (and __iter__ returning itself)
