Um iterable é tudo aquilo sobre o qual você pode fazer um loop (uma lista, string, dict); um iterator é o objeto que faz a iteração real, produzindo valores um de cada vez e rastreando sua posição. Essa distinção fundamenta como os loops for funcionam em Python.
Os dois protocolos
Iterable → has __iter__() → returns an iterator
Iterator → has __next__() → returns the next value (and __iter__ returning itself)
