Superficially that&#x27;s a common difference that will be noticed.<p>The thing that sets generators apart from other iterable types in Python, though, is actually the fact that generators are units of code which can suspend their execution, then resume it at a later time (and in more recent versions of Python, can have additional information passed into them while doing so).<p>Formally, a generator is a callable whose body contains at least one yield expression. So for example when you pull the values out of it (the way you would with an ordinary iterable) what happens is that it executes until it encounters a yield, emits whatever value is specified by the yield, and suspends execution. The next time it&#x27;s asked for a value, it resumes execution until it encounters a yield again. You can continue in this way until either 1) the generator executes a &#x27;return&#x27; statement, or 2) control flows past the end of the generator&#x27;s code, or 3) the generator raises a StopIteration exception (and in the first two cases a StopIteration gets raised for you by Python, so that you don&#x27;t have to explicitly do it if you don&#x27;t want to).<p>This means generators can be used to implement lazy iterables, infinite iterables, etc., but also means generators can be used as coroutines by taking advantage of their ability to suspend&#x2F;resume and pass control flow around.