[{"data":1,"prerenderedAt":71},["ShallowReactive",2],{"qa-\u002Fpython\u002Fiteration\u002Fiterators":3},{"page":4,"siblings":58,"blog":49},{"id":5,"title":6,"body":7,"description":11,"difficulty":14,"extension":15,"framework":16,"frameworkSlug":17,"meta":18,"navigation":19,"order":20,"path":21,"questions":22,"related":49,"seo":50,"seoDescription":51,"stem":52,"subtopic":53,"topic":54,"topicSlug":55,"updated":56,"__hash__":57},"qa\u002Fpython\u002Fiteration\u002Fiterators.md","Iterators",{"type":8,"value":9,"toc":10},"minimark",[],{"title":11,"searchDepth":12,"depth":12,"links":13},"",2,[],"medium","md","Python","python",{},true,3,"\u002Fpython\u002Fiteration\u002Fiterators",[23,27,31,36,40,45],{"id":24,"difficulty":14,"q":25,"a":26},"iterable-vs-iterator","What is the difference between an iterable and an iterator?","An **iterable** is anything you can loop over — it knows how to produce an\niterator via `__iter__`. An **iterator** is the object that actually does\nthe walking: it has `__next__` and yields one value at a time, remembering\nits position. Every iterator is iterable (its `__iter__` returns itself),\nbut not every iterable is an iterator.\n\n```python\nnums = [1, 2, 3]          # list: iterable, NOT an iterator\nit = iter(nums)           # iterator over the list\nnext(it)                  # 1  — iterators track position\nnext(it)                  # 2\n```\n\nThink of the iterable as the *collection* and the iterator as a\n*cursor\u002Fbookmark* into it. You can create many independent iterators from\none iterable.\n",{"id":28,"difficulty":14,"q":29,"a":30},"iter-next-protocol","What methods make up the iterator protocol?","The **iterator protocol** is two methods. `__iter__` must return the\niterator object itself, and `__next__` returns the next value or raises\n**`StopIteration`** when exhausted. That exception is the agreed signal\nthat there are no more items.\n\n```python\nit = iter([10, 20])\nit.__next__()      # 10\nit.__next__()      # 20\nit.__next__()      # raises StopIteration\n```\n\nAn **iterable** only needs `__iter__` (returning a fresh iterator). An\n**iterator** needs both. The `StopIteration` raise is what lets `for` loops\nknow when to stop — they catch it silently.\n",{"id":32,"difficulty":33,"q":34,"a":35},"iter-next-builtins","easy","What do the built-in iter() and next() functions do?","`iter(obj)` calls `obj.__iter__()` to get an iterator; `next(it)` calls\n`it.__next__()` to advance it. `next()` accepts an optional **default** that\nis returned instead of raising `StopIteration` when the iterator is\nexhausted — handy for safe peeking.\n\n```python\nit = iter(\"ab\")\nnext(it)            # 'a'\nnext(it)            # 'b'\nnext(it, \"done\")    # 'done'  — default instead of StopIteration\n\n# iter() also has a two-arg sentinel form:\n# iter(callable, sentinel) calls until it returns sentinel\n```\n\nUse the default argument whenever you want to drain or sample an iterator\nwithout wrapping `next()` in a `try`\u002F`except StopIteration`.\n",{"id":37,"difficulty":14,"q":38,"a":39},"custom-iterator-class","How do you build a custom iterator class?","Implement `__iter__` (return `self`) and `__next__` (return the next value\nor raise `StopIteration`). The instance holds its own state between calls.\n\n```python\nclass Countdown:\n    def __init__(self, start):\n        self.n = start\n    def __iter__(self):\n        return self\n    def __next__(self):\n        if self.n \u003C= 0:\n            raise StopIteration\n        self.n -= 1\n        return self.n + 1\n\nlist(Countdown(3))     # [3, 2, 1]\n```\n\nThis works, but for most cases a **generator function** (using `yield`) is\nfar less boilerplate — it builds the `__iter__`\u002F`__next__`\u002F`StopIteration`\nmachinery for you. Reach for a class only when you need extra methods or\nexplicit state.\n",{"id":41,"difficulty":42,"q":43,"a":44},"for-under-the-hood","hard","How does a for loop work under the hood?","A `for` loop is sugar over the iterator protocol. Python calls `iter()` on\nthe iterable once to get an iterator, then repeatedly calls `next()` on it,\nbinding each result to the loop variable, until `StopIteration` is raised —\nwhich it catches to end the loop.\n\n```python\nfor x in [1, 2, 3]:\n    print(x)\n\n# is roughly equivalent to:\n_it = iter([1, 2, 3])\nwhile True:\n    try:\n        x = next(_it)\n    except StopIteration:\n        break\n    print(x)\n```\n\nThis is why any object implementing the protocol \"just works\" in a `for`\nloop, comprehension, or `*`-unpacking. The `StopIteration` is the hidden\nhandshake that terminates the loop.\n",{"id":46,"difficulty":14,"q":47,"a":48},"iterator-exhaustion","Why can you only iterate an iterator once?","An iterator is **single-use \u002F exhaustible**: once `__next__` has walked to\nthe end and raised `StopIteration`, it stays exhausted — there is no reset.\nRe-iterating yields nothing. This trips people up with generators and\n`zip`\u002F`map` objects.\n\n```python\nit = iter([1, 2, 3])\nlist(it)     # [1, 2, 3]\nlist(it)     # []  — already exhausted!\n\ngen = (x for x in range(3))\nsum(gen)     # 3\nsum(gen)     # 0  — the generator is spent\n```\n\nA **list** (an iterable, not an iterator) can be looped many times because\neach loop calls `iter()` to get a *fresh* iterator. If you need to reuse an\nexhaustible result, materialize it into a list first.\n",null,{"description":11},"Python interview questions on iterables vs iterators, the iterator protocol, __iter__ and __next__, StopIteration, building custom iterators, and how for loops work under the hood.","python\u002Fiteration\u002Fiterators","Iterators & the Iterator Protocol","Comprehensions & Iteration","iteration","2026-06-18","MDIPCY-D1tLVqU5RVp-SI3ZbPEO4RflTJJO17wGSu24",[59,63,66,67],{"subtopic":60,"path":61,"order":62},"Generators & yield","\u002Fpython\u002Fiteration\u002Fgenerators",1,{"subtopic":64,"path":65,"order":12},"List, Dict & Set Comprehensions","\u002Fpython\u002Fiteration\u002Fcomprehensions",{"subtopic":53,"path":21,"order":20},{"subtopic":68,"path":69,"order":70},"enumerate, zip & Unpacking","\u002Fpython\u002Fiteration\u002Fenumerate-zip",4,1781808679853]