@@ -168,107 +168,137 @@ have fast appends and pops from both ends. For example::
168168List Comprehensions
169169-------------------
170170
171- List comprehensions provide a concise way to create lists from sequences .
172- Common applications are to make lists where each element is the result of
173- some operations applied to each member of the sequence, or to create a
174- subsequence of those elements that satisfy a certain condition.
171+ List comprehensions provide a concise way to create lists.
172+ Common applications are to make new lists where each element is the result of
173+ some operations applied to each member of another sequence or iterable, or to
174+ create a subsequence of those elements that satisfy a certain condition.
175175
176- A list comprehension consists of brackets containing an expression followed
177- by a :keyword: `for ` clause, then zero or more :keyword: `for ` or :keyword: `if `
178- clauses. The result will be a list resulting from evaluating the expression in
179- the context of the :keyword: `for ` and :keyword: `if ` clauses which follow it. If
180- the expression would evaluate to a tuple, it must be parenthesized.
176+ For example, assume we want to create a list of squares, like::
177+
178+ >>> squares = []
179+ >>> for x in range(10):
180+ ... squares.append(x**2)
181+ ...
182+ >>> squares
183+ [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
184+
185+ We can obtain the same result with::
181186
182- Here we take a list of numbers and return a list of three times each number::
187+ squares = [x**2 for x in range(10)]
183188
184- >>> vec = [2, 4, 6]
185- >>> [3*x for x in vec]
186- [6, 12, 18]
189+ This is also equivalent to ``squares = map(lambda x: x**2, range(10)) ``,
190+ but it's more concise and readable.
187191
188- Now we get a little fancier::
192+ A list comprehension consists of brackets containing an expression followed
193+ by a :keyword: `for ` clause, then zero or more :keyword: `for ` or :keyword: `if `
194+ clauses. The result will be a new list resulting from evaluating the expression
195+ in the context of the :keyword: `for ` and :keyword: `if ` clauses which follow it.
196+ For example, this listcomp combines the elements of two lists if they are not
197+ equal::
189198
190- >>> [[ x, x**2 ] for x in vec ]
191- [[2, 4], [4, 16], [6, 36] ]
199+ >>> [( x, y) for x in [1,2,3 ] for y in [3,1,4] if x != y ]
200+ [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4) ]
192201
193- Here we apply a method call to each item in a sequence ::
202+ and it's equivalent to ::
194203
204+ >>> combs = []
205+ >>> for x in [1,2,3]:
206+ ... for y in [3,1,4]:
207+ ... if x != y:
208+ ... combs.append((x, y))
209+ ...
210+ >>> combs
211+ [(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
212+
213+ Note how the order of the :keyword: `for ` and :keyword: `if ` statements is the
214+ same in both these snippets.
215+
216+ If the expression is a tuple (e.g. the ``(x, y) `` in the previous example),
217+ it must be parenthesized. ::
218+
219+ >>> vec = [-4, -2, 0, 2, 4]
220+ >>> # create a new list with the values doubled
221+ >>> [x*2 for x in vec]
222+ [-8, -4, 0, 4, 8]
223+ >>> # filter the list to exclude negative numbers
224+ >>> [x for x in vec if x >= 0]
225+ [0, 2, 4]
226+ >>> # apply a function to all the elements
227+ >>> [abs(x) for x in vec]
228+ [4, 2, 0, 2, 4]
229+ >>> # call a method on each element
195230 >>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
196231 >>> [weapon.strip() for weapon in freshfruit]
197232 ['banana', 'loganberry', 'passion fruit']
198-
199- Using the :keyword: `if ` clause we can filter the stream::
200-
201- >>> [3*x for x in vec if x > 3]
202- [12, 18]
203- >>> [3*x for x in vec if x < 2]
204- []
205-
206- Tuples can often be created without their parentheses, but not here::
207-
208- >>> [x, x**2 for x in vec] # error - parens required for tuples
233+ >>> # create a list of 2-tuples like (number, square)
234+ >>> [(x, x**2) for x in range(6)]
235+ [(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
236+ >>> # the tuple must be parenthesized, otherwise an error is raised
237+ >>> [x, x**2 for x in range(6)]
209238 File "<stdin>", line 1, in ?
210- [x, x**2 for x in vec ]
239+ [x, x**2 for x in range(6) ]
211240 ^
212241 SyntaxError: invalid syntax
213- >>> [(x, x**2) for x in vec]
214- [(2, 4), (4, 16), (6, 36)]
215-
216- Here are some nested for loops and other fancy behavior::
217-
218- >>> vec1 = [2, 4, 6]
219- >>> vec2 = [4, 3, -9]
220- >>> [x*y for x in vec1 for y in vec2]
221- [8, 6, -18, 16, 12, -36, 24, 18, -54]
222- >>> [x+y for x in vec1 for y in vec2]
223- [6, 5, -7, 8, 7, -5, 10, 9, -3]
224- >>> [vec1[i]*vec2[i] for i in range(len(vec1))]
225- [8, 12, -54]
242+ >>> # flatten a list using a listcomp with two 'for'
243+ >>> vec = [[1,2,3], [4,5,6], [7,8,9]]
244+ >>> [num for elem in vec for num in elem]
245+ [1, 2, 3, 4, 5, 6, 7, 8, 9]
226246
227- List comprehensions can be applied to complex expressions and nested functions::
247+ List comprehensions can contain complex expressions and nested functions::
228248
229- >>> [str(round(355/113, i)) for i in range(1, 6)]
249+ >>> from math import pi
250+ >>> [str(round(pi, i)) for i in range(1, 6)]
230251 ['3.1', '3.14', '3.142', '3.1416', '3.14159']
231252
232-
233253Nested List Comprehensions
234254--------------------------
235255
236- If you've got the stomach for it, list comprehensions can be nested. They are a
237- powerful tool but -- like all powerful tools -- they need to be used carefully,
238- if at all.
239-
240- Consider the following example of a 3x3 matrix held as a list containing three
241- lists, one list per row::
242-
243- >>> mat = [
244- ... [1, 2, 3],
245- ... [4, 5, 6],
246- ... [7, 8, 9],
247- ... ]
256+ The initial expression in a list comprehension can be any arbitrary expression,
257+ including another list comprehension.
248258
249- Now, if you wanted to swap rows and columns, you could use a list
250- comprehension ::
259+ Consider the following example of a 3x4 matrix implemented as a list of
260+ 3 lists of length 4 ::
251261
252- >>> print([[row[i] for row in mat] for i in [0, 1, 2]])
253- [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
262+ >>> matrix = [
263+ ... [1, 2, 3, 4],
264+ ... [5, 6, 7, 8],
265+ ... [9, 10, 11, 12],
266+ ... ]
254267
255- Special care has to be taken for the * nested * list comprehension :
268+ The following list comprehension will transpose rows and columns: :
256269
257- To avoid apprehension when nesting list comprehensions, read from right to
258- left.
270+ >>> [[row[i] for row in matrix] for i in range(4)]
271+ [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
259272
260- A more verbose version of this snippet shows the flow explicitly::
273+ As we saw in the previous section, the nested listcomp is evaluated in
274+ the context of the :keyword: `for ` that follows it, so this example is
275+ equivalent to::
261276
262- for i in [0, 1, 2]:
263- for row in mat:
264- print(row[i], end="")
265- print()
277+ >>> transposed = []
278+ >>> for i in range(4):
279+ ... transposed.append([row[i] for row in matrix])
280+ ...
281+ >>> transposed
282+ [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
283+
284+ which, in turn, is the same as::
285+
286+ >>> transposed = []
287+ >>> for i in range(4):
288+ ... # the following 3 lines implement the nested listcomp
289+ ... transposed_row = []
290+ ... for row in matrix:
291+ ... transposed_row.append(row[i])
292+ ... transposed.append(transposed_row)
293+ ...
294+ >>> transposed
295+ [[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
266296
267- In real world, you should prefer built-in functions to complex flow statements.
297+ In the real world, you should prefer built-in functions to complex flow statements.
268298The :func: `zip ` function would do a great job for this use case::
269299
270- >>> list( zip(*mat) )
271- [(1, 4, 7 ), (2, 5, 8 ), (3, 6, 9 )]
300+ >>> zip(*matrix )
301+ [(1, 5, 9 ), (2, 6, 10 ), (3, 7, 11), (4, 8, 12 )]
272302
273303See :ref: `tut-unpacking-arguments ` for details on the asterisk in this line.
274304
0 commit comments