Index: Doc/ref/ref5.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/ref/ref5.tex,v retrieving revision 1.80 diff -c -r1.80 ref5.tex *** Doc/ref/ref5.tex 23 Apr 2004 17:11:47 -0000 1.80 --- Doc/ref/ref5.tex 20 May 2004 15:53:15 -0000 *************** *** 55,61 **** {\token{identifier} | \token{literal} | \token{enclosure}} \production{enclosure} {\token{parenth_form} | \token{list_display}} ! \productioncont{| \token{dict_display} | \token{string_conversion}} \end{productionlist} --- 55,62 ---- {\token{identifier} | \token{literal} | \token{enclosure}} \production{enclosure} {\token{parenth_form} | \token{list_display}} ! \productioncont{| \token{dict_display} | \token{generator_expression}} ! \productioncont{| \token{string_conversion}} \end{productionlist} *************** *** 222,227 **** --- 223,270 ---- \indexii{immutable}{object} + \subsection{Generator expressions\label{genexpr}} + \indexii{generator}{expression} + + A generator expression is a compact generator notation in parentheses: + + \begin{productionlist} + \production{generator_expression} + {"(" \token{test} \token{genexpr_for} ")"} + \production{genexpr_for} + {"for" \token{expression_list} "in" \token{test} + [\token{genexpr_iter}]} + \production{genexpr_iter} + {\token{genexpr_for} | \token{genexpr_if}} + \production{genexpr_if} + {"if" \token{test} [\token{genexpr_iter}]} + \end{productionlist} + + A generator expression yields a new generator object. + \obindex{generator} + \obindex{generator expression} + It consists of a single expression followed by at least one + \keyword{for} clause and zero or more \keyword{for} or \keyword{if} + clauses. The iterating values of the new generator are those that + would be produced by considering each of the \keyword{for} or + \keyword{if} clauses a block, nesting from left to right, and + evaluating the expression to yield a value that is reached the + innermost block for each iteration. + + Variables used in the generator expression is evaluated lazily + - when next() method is called for generator object - , + just like normal generators. However, the leftmost \keyword{for} + clause is immediately evaluated so that error produced by it + can be seen before any other possible error in the code that + handles the generator expression. + The subsequent \keyword{for} clause cannot be evaluated immediately since + it might be dependant on the previous \keyword{for} loop. + e.g. (x*y for x in range(10) for y in bar(x)) + + The parentheses can be omitted on calls with only one argument. + See section \ref{calls} for the detail. + + \subsection{String conversions\label{string-conversions}} \indexii{string}{conversion} \indexii{reverse}{quotes} *************** *** 427,433 **** \begin{productionlist} \production{call} ! {\token{primary} "(" [\token{argument_list} [","]] ")"} \production{argument_list} {\token{positional_arguments} ["," \token{keyword_arguments}]} \productioncont{ ["," "*" \token{expression}]} --- 470,477 ---- \begin{productionlist} \production{call} ! {\token{primary} "(" [ \token{argument_list} [","] | ! \token{test} \token{genexpr_for} ] ")"} \production{argument_list} {\token{positional_arguments} ["," \token{keyword_arguments}]} \productioncont{ ["," "*" \token{expression}]} Index: Doc/tut/tut.tex =================================================================== RCS file: /cvsroot/python/python/dist/src/Doc/tut/tut.tex,v retrieving revision 1.227 diff -c -r1.227 tut.tex *** Doc/tut/tut.tex 6 May 2004 01:35:45 -0000 1.227 --- Doc/tut/tut.tex 20 May 2004 15:53:18 -0000 *************** *** 4399,4404 **** --- 4399,4468 ---- In combination, these features make it easy to create iterators with no more effort than writing a regular function. + Just like you can use a lambda expression instead of a function + when you don't need complicated work, you can use generator + expression instead of generator when things you want to do + are simple. Generator expression is similar to list comprehensions, + except that it gives a generator object instead of a list. + Each generator expression consists of an expression + followed by a for clause, then zero or more for or if clauses. + Following examples show how to use generator expression. + + \begin{verbatim} + >>> sum(x**2 for x in range(10)) + 285 + + >>> min(ch.upper() for ch in 'They killed Kenny!' if ch.islower()) + 'D' + + >>> data = 'live' + >>> '/'.join(data[index] for index in range(len(data)-1, -1, -1)) + 'e/v/i/l' + + >>> (x for x in range(100) if x**2 > 1000).next() + 32 + + >>> g = ('%02x' % ord(c) for c in 'hello') + >>> g.next(); g.next(); g.next(); + '68' + '65' + '6c' + + >>> g = ((x, y, x*y) for x in range(2) for y in range(2)) + >>> for v in g: + ... print v + ... + (0, 0, 0) + (0, 1, 0) + (1, 0, 0) + (1, 1, 1) + + \end{verbatim} + + Generator expression should be used carefully when + it's not used up immediately, for it might not work + the way you expected it to be. For instance, see + following example: + + \begin{verbatim} + >>> x=4 + >>> g=((i,j) for i in range(x) for j in range(x)) + >>> x=2 + >>> list(g) + [(0, 0), (0, 1), (1, 0), (1, 1), (2, 0), (2, 1), (3, 0), (3, 1)] + \end{verbatim} + + Here, in the generator expression, variable i was iterated upto 4 + but variable j was iterated upto 2, even though both use range(x) + for iterator. That's because variables in the generator expression + are evaluated lazily, while leftmost for clause is immediately + evaluated. So, in the above example, the first range(x) is computed + in the creation time while the second range(x) is evaluated when + list(g) is called. It works like that to get possible errors + as soon as possible. (Subsequent for clause cannot be precomputed, + since it might depend on the previous for clause.) If this feature + bothers you, you can always explicitly use generator function + instead of generator expression. \chapter{Brief Tour of the Standard Library \label{briefTour}}