To put it another way, a list comprehension or generator expression is equivalent to the following Python code: This means that when there are multiple for...in clauses but no if clauses, the length of the resulting output will be equal to the product of the lengths of all the sequences. If you have two lists of length 3, the output list is 9 elements long: To avoid introducing an ambiguity into Python’s grammar, if$_{expression}$ is creating a tuple, it must be surrounded with parentheses. The first list comprehension below is a syntax error, while the second one is correct: Generators are a special class of functions that simplify the task of writing iterators. Regular functions compute a value and return it, but generators return an iterator that returns a stream of values. You’re doubtless familiar with how regular function calls work in Python or C. When you call a function, it gets a private namespace where its local variables are created. When the function reaches a$_{return}$statement, the local variables are destroyed and the value is returned to the caller. A later call to the same function creates a new private namespace and a fresh set of local variables. But, what if the local variables weren’t thrown away on exiting a function? What if you could later resume the function where it left off? This is what generators provide; they can be thought of as resumable functions. Here’s the simplest example of a generator function: Any function containing a$_{yield}$ keyword is a generator function; this is detected by Python’s bytecode compiler which compiles the function specially as a result. When you call a generator function, it doesn’t return a single value; instead it returns a generator object that supports the iterator protocol. On executing the$_{yield}$ expression, the generator outputs the value of$_{i}$ , similar to a$_{return}$ statement. The big difference between$_{yield}$ and a$_{return}$statement is that on reaching a$_{yield}$ the generator’s 7 >>> def generate_ints(N): ... for i in range(N): ... yield i # Syntax error [x, y for x in seq1 for y in seq2] # Correct [(x, y) for x in seq1 for y in seq2] >>> seq1='abc' >>> seq2=(1,2,3) >>> [(x, y) for x in seq1 for y in seq2] [('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1), ('c', 2), ('c', 3)] for expr1 in sequence1: if not (condition1): continue # Skip this element for expr2 in sequence2: if not (condition2): continue # Skip this element ... for exprN in sequenceN: if not (conditionN): continue # Skip this element # Output the value of # the expression. 4 Generators