Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
d31d57e2
Commit
d31d57e2
authored
Dec 13, 2011
by
Ezio Melotti
Browse files
Options
Browse Files
Download
Plain Diff
#13549: merge with 3.2.
parents
ca2a1a33
91621e2c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
102 additions
and
72 deletions
+102
-72
Doc/tutorial/datastructures.rst
Doc/tutorial/datastructures.rst
+102
-72
No files found.
Doc/tutorial/datastructures.rst
View file @
d31d57e2
...
@@ -168,107 +168,137 @@ have fast appends and pops from both ends. For example::
...
@@ -168,107 +168,137 @@ have fast appends and pops from both ends. For example::
List Comprehensions
List Comprehensions
-------------------
-------------------
List comprehensions provide a concise way to create lists
from sequences
.
List comprehensions provide a concise way to create lists.
Common applications are to make lists where each element is the result of
Common applications are to make
new
lists where each element is the result of
some operations applied to each member of
the sequence, or to create a
some operations applied to each member of
another sequence or iterable, or to
subsequence of those elements that satisfy a certain condition.
create a
subsequence of those elements that satisfy a certain condition.
A list comprehension consists of brackets containing an expression followed
For example, assume we want to create a list of squares, like::
by a :keyword:`for` clause, then zero or more :keyword:`for` or :keyword:`if`
clauses. The result will be a list resulting from evaluating the expression in
>>> squares = []
the context of the :keyword:`for` and :keyword:`if` clauses which follow it. If
>>> for x in range(10):
the expression would evaluate to a tuple, it must be parenthesized.
... squares.append(x**2)
...
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
We can obtain the same result with::
Here we take a list of numbers and return a list of three times each number::
squares = [x**2 for x in range(10)]
>>> vec = [2, 4, 6]
This is also equivalent to ``squares = map(lambda x: x**2, range(10))``,
>>> [3*x for x in vec]
but it's more concise and readable.
[6, 12, 18]
Now we get a little fancier::
A list comprehension consists of brackets containing an expression followed
by a :keyword:`for` clause, then zero or more :keyword:`for` or :keyword:`if`
clauses. The result will be a new list resulting from evaluating the expression
in the context of the :keyword:`for` and :keyword:`if` clauses which follow it.
For example, this listcomp combines the elements of two lists if they are not
equal::
>>> [
[x, x**2] for x in vec
]
>>> [
(x, y) for x in [1,2,3] for y in [3,1,4] if x != y
]
[
[2, 4], [4, 16], [6, 36]
]
[
(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)
]
Here we apply a method call to each item in a sequence
::
and it's equivalent to
::
>>> combs = []
>>> for x in [1,2,3]:
... for y in [3,1,4]:
... if x != y:
... combs.append((x, y))
...
>>> combs
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
Note how the order of the :keyword:`for` and :keyword:`if` statements is the
same in both these snippets.
If the expression is a tuple (e.g. the ``(x, y)`` in the previous example),
it must be parenthesized. ::
>>> vec = [-4, -2, 0, 2, 4]
>>> # create a new list with the values doubled
>>> [x*2 for x in vec]
[-8, -4, 0, 4, 8]
>>> # filter the list to exclude negative numbers
>>> [x for x in vec if x >= 0]
[0, 2, 4]
>>> # apply a function to all the elements
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
>>> # call a method on each element
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> freshfruit = [' banana', ' loganberry ', 'passion fruit ']
>>> [weapon.strip() for weapon in freshfruit]
>>> [weapon.strip() for weapon in freshfruit]
['banana', 'loganberry', 'passion fruit']
['banana', 'loganberry', 'passion fruit']
>>> # create a list of 2-tuples like (number, square)
Using the :keyword:`if` clause we can filter the stream::
>>> [(x, x**2) for x in range(6)]
[(0, 0), (1, 1), (2, 4), (3, 9), (4, 16), (5, 25)]
>>> [3*x for x in vec if x > 3]
>>> # the tuple must be parenthesized, otherwise an error is raised
[12, 18]
>>> [x, x**2 for x in range(6)]
>>> [3*x for x in vec if x < 2]
[]
Tuples can often be created without their parentheses, but not here::
>>> [x, x**2 for x in vec] # error - parens required for tuples
File "<stdin>", line 1, in ?
File "<stdin>", line 1, in ?
[x, x**2 for x in
vec
]
[x, x**2 for x in
range(6)
]
^
^
SyntaxError: invalid syntax
SyntaxError: invalid syntax
>>> [(x, x**2) for x in vec]
>>> # flatten a list using a listcomp with two 'for'
[(2, 4), (4, 16), (6, 36)]
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
Here are some nested for loops and other fancy behavior::
[1, 2, 3, 4, 5, 6, 7, 8, 9]
>>> vec1 = [2, 4, 6]
>>> vec2 = [4, 3, -9]
>>> [x*y for x in vec1 for y in vec2]
[8, 6, -18, 16, 12, -36, 24, 18, -54]
>>> [x+y for x in vec1 for y in vec2]
[6, 5, -7, 8, 7, -5, 10, 9, -3]
>>> [vec1[i]*vec2[i] for i in range(len(vec1))]
[8, 12, -54]
List comprehensions can
be applied to
complex expressions and nested functions::
List comprehensions can
contain
complex expressions and nested functions::
>>> [str(round(355/113, i)) for i in range(1, 6)]
>>> from math import pi
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
['3.1', '3.14', '3.142', '3.1416', '3.14159']
Nested List Comprehensions
Nested List Comprehensions
--------------------------
--------------------------
If you've got the stomach for it, list comprehensions can be nested. They are a
The initial expression in a list comprehension can be any arbitrary expression,
powerful tool but -- like all powerful tools -- they need to be used carefully,
including another list comprehension.
if at all.
Consider the following example of a 3x3 matrix held as a list containing three
lists, one list per row::
>>> mat = [
... [1, 2, 3],
... [4, 5, 6],
... [7, 8, 9],
... ]
Now, if you wanted to swap rows and columns, you could use a list
Consider the following example of a 3x4 matrix implemented as a list of
comprehension
::
3 lists of length 4
::
>>> print([[row[i] for row in mat] for i in [0, 1, 2]])
>>> matrix = [
[[1, 4, 7], [2, 5, 8], [3, 6, 9]]
... [1, 2, 3, 4],
... [5, 6, 7, 8],
... [9, 10, 11, 12],
... ]
Special care has to be taken for the *nested* list comprehension
:
The following list comprehension will transpose rows and columns:
:
To avoid apprehension when nesting list comprehensions, read from right to
>>> [[row[i] for row in matrix] for i in range(4)]
left.
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
A more verbose version of this snippet shows the flow explicitly::
As we saw in the previous section, the nested listcomp is evaluated in
the context of the :keyword:`for` that follows it, so this example is
equivalent to::
for i in [0, 1, 2]:
>>> transposed = []
for row in mat:
>>> for i in range(4):
print(row[i], end="")
... transposed.append([row[i] for row in matrix])
print()
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
which, in turn, is the same as::
>>> transposed = []
>>> for i in range(4):
... # the following 3 lines implement the nested listcomp
... transposed_row = []
... for row in matrix:
... transposed_row.append(row[i])
... transposed.append(transposed_row)
...
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
In real world, you should prefer built-in functions to complex flow statements.
In
the
real world, you should prefer built-in functions to complex flow statements.
The :func:`zip` function would do a great job for this use case::
The :func:`zip` function would do a great job for this use case::
>>> list(zip(*mat)
)
>>> zip(*matrix
)
[(1, 4, 7), (2, 5, 8), (3, 6, 9
)]
[(1, 5, 9), (2, 6, 10), (3, 7, 11), (4, 8, 12
)]
See :ref:`tut-unpacking-arguments` for details on the asterisk in this line.
See :ref:`tut-unpacking-arguments` for details on the asterisk in this line.
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment