summaryrefslogtreecommitdiffstats
path: root/Doc/tutorial/datastructures.rst
diff options
context:
space:
mode:
Diffstat (limited to 'Doc/tutorial/datastructures.rst')
-rw-r--r--Doc/tutorial/datastructures.rst318
1 files changed, 181 insertions, 137 deletions
diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst
index 2f7afb0..4e60e32 100644
--- a/Doc/tutorial/datastructures.rst
+++ b/Doc/tutorial/datastructures.rst
@@ -7,6 +7,7 @@ Data Structures
This chapter describes some things you've learned about already in more detail,
and adds some new things as well.
+
.. _tut-morelists:
More on Lists
@@ -19,14 +20,14 @@ objects:
.. method:: list.append(x)
:noindex:
- Add an item to the end of the list. Equivalent to ``a[len(a):] = [x]``.
+ Add an item to the end of the list; equivalent to ``a[len(a):] = [x]``.
-.. method:: list.extend(iterable)
+.. method:: list.extend(L)
:noindex:
- Extend the list by appending all the items from the iterable. Equivalent to
- ``a[len(a):] = iterable``.
+ Extend the list by appending all the items in the given list; equivalent to
+ ``a[len(a):] = L``.
.. method:: list.insert(i, x)
@@ -40,8 +41,8 @@ objects:
.. method:: list.remove(x)
:noindex:
- Remove the first item from the list whose value is equal to *x*. It raises a
- :exc:`ValueError` if there is no such item.
+ Remove the first item from the list whose value is *x*. It is an error if there
+ is no such item.
.. method:: list.pop([i])
@@ -54,22 +55,11 @@ objects:
will see this notation frequently in the Python Library Reference.)
-.. method:: list.clear()
- :noindex:
-
- Remove all items from the list. Equivalent to ``del a[:]``.
-
-
-.. method:: list.index(x[, start[, end]])
+.. method:: list.index(x)
:noindex:
- Return zero-based index in the list of the first item whose value is equal to *x*.
- Raises a :exc:`ValueError` if there is no such item.
-
- The optional arguments *start* and *end* are interpreted as in the slice
- notation and are used to limit the search to a particular subsequence of
- the list. The returned index is computed relative to the beginning of the full
- sequence rather than the *start* argument.
+ Return the index in the list of the first item whose value is *x*. It is an
+ error if there is no such item.
.. method:: list.count(x)
@@ -78,7 +68,7 @@ objects:
Return the number of times *x* appears in the list.
-.. method:: list.sort(key=None, reverse=False)
+.. method:: list.sort(cmp=None, key=None, reverse=False)
:noindex:
Sort the items of the list in place (the arguments can be used for sort
@@ -88,50 +78,38 @@ objects:
.. method:: list.reverse()
:noindex:
- Reverse the elements of the list in place.
-
-
-.. method:: list.copy()
- :noindex:
-
- Return a shallow copy of the list. Equivalent to ``a[:]``.
-
+ Reverse the elements of the list, in place.
An example that uses most of the list methods::
- >>> fruits = ['orange', 'apple', 'pear', 'banana', 'kiwi', 'apple', 'banana']
- >>> fruits.count('apple')
- 2
- >>> fruits.count('tangerine')
- 0
- >>> fruits.index('banana')
- 3
- >>> fruits.index('banana', 4) # Find next banana starting a position 4
- 6
- >>> fruits.reverse()
- >>> fruits
- ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange']
- >>> fruits.append('grape')
- >>> fruits
- ['banana', 'apple', 'kiwi', 'banana', 'pear', 'apple', 'orange', 'grape']
- >>> fruits.sort()
- >>> fruits
- ['apple', 'apple', 'banana', 'banana', 'grape', 'kiwi', 'orange', 'pear']
- >>> fruits.pop()
- 'pear'
+ >>> a = [66.25, 333, 333, 1, 1234.5]
+ >>> print a.count(333), a.count(66.25), a.count('x')
+ 2 1 0
+ >>> a.insert(2, -1)
+ >>> a.append(333)
+ >>> a
+ [66.25, 333, -1, 333, 1, 1234.5, 333]
+ >>> a.index(333)
+ 1
+ >>> a.remove(333)
+ >>> a
+ [66.25, -1, 333, 1, 1234.5, 333]
+ >>> a.reverse()
+ >>> a
+ [333, 1234.5, 1, 333, -1, 66.25]
+ >>> a.sort()
+ >>> a
+ [-1, 1, 66.25, 333, 333, 1234.5]
+ >>> a.pop()
+ 1234.5
+ >>> a
+ [-1, 1, 66.25, 333, 333]
You might have noticed that methods like ``insert``, ``remove`` or ``sort`` that
only modify the list have no return value printed -- they return the default
-``None``. [1]_ This is a design principle for all mutable data structures in
+``None``. This is a design principle for all mutable data structures in
Python.
-Another thing you might notice is that not all data can be sorted or
-compared. For instance, ``[None, 'hello', 10]`` doesn't sort because
-integers can't be compared to strings and *None* can't be compared to
-other types. Also, there are some types that don't have a defined
-ordering relation. For example, ``3+4j < 5+7j`` isn't a valid
-comparison.
-
.. _tut-lists-as-stacks:
@@ -191,6 +169,76 @@ have fast appends and pops from both ends. For example::
deque(['Michael', 'Terry', 'Graham'])
+.. _tut-functional:
+
+Functional Programming Tools
+----------------------------
+
+There are three built-in functions that are very useful when used with lists:
+:func:`filter`, :func:`map`, and :func:`reduce`.
+
+``filter(function, sequence)`` returns a sequence consisting of those items from
+the sequence for which ``function(item)`` is true. If *sequence* is a
+:class:`str`, :class:`unicode` or :class:`tuple`, the result will be of the
+same type; otherwise, it is always a :class:`list`. For example, to compute a
+sequence of numbers divisible by 3 or 5::
+
+ >>> def f(x): return x % 3 == 0 or x % 5 == 0
+ ...
+ >>> filter(f, range(2, 25))
+ [3, 5, 6, 9, 10, 12, 15, 18, 20, 21, 24]
+
+``map(function, sequence)`` calls ``function(item)`` for each of the sequence's
+items and returns a list of the return values. For example, to compute some
+cubes::
+
+ >>> def cube(x): return x*x*x
+ ...
+ >>> map(cube, range(1, 11))
+ [1, 8, 27, 64, 125, 216, 343, 512, 729, 1000]
+
+More than one sequence may be passed; the function must then have as many
+arguments as there are sequences and is called with the corresponding item from
+each sequence (or ``None`` if some sequence is shorter than another). For
+example::
+
+ >>> seq = range(8)
+ >>> def add(x, y): return x+y
+ ...
+ >>> map(add, seq, seq)
+ [0, 2, 4, 6, 8, 10, 12, 14]
+
+``reduce(function, sequence)`` returns a single value constructed by calling the
+binary function *function* on the first two items of the sequence, then on the
+result and the next item, and so on. For example, to compute the sum of the
+numbers 1 through 10::
+
+ >>> def add(x,y): return x+y
+ ...
+ >>> reduce(add, range(1, 11))
+ 55
+
+If there's only one item in the sequence, its value is returned; if the sequence
+is empty, an exception is raised.
+
+A third argument can be passed to indicate the starting value. In this case the
+starting value is returned for an empty sequence, and the function is first
+applied to the starting value and the first sequence item, then to the result
+and the next item, and so on. For example, ::
+
+ >>> def sum(seq):
+ ... def add(x,y): return x+y
+ ... return reduce(add, seq, 0)
+ ...
+ >>> sum(range(1, 11))
+ 55
+ >>> sum([])
+ 0
+
+Don't use this example's definition of :func:`sum`: since summing numbers is
+such a common need, a built-in function ``sum(sequence)`` is already provided,
+and works exactly like this.
+
.. _tut-listcomps:
List Comprehensions
@@ -210,29 +258,24 @@ For example, assume we want to create a list of squares, like::
>>> squares
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
-Note that this creates (or overwrites) a variable named ``x`` that still exists
-after the loop completes. We can calculate the list of squares without any
-side effects using::
-
- squares = list(map(lambda x: x**2, range(10)))
-
-or, equivalently::
+We can obtain the same result with::
squares = [x**2 for x in range(10)]
-which is more concise and readable.
+This is also equivalent to ``squares = map(lambda x: x**2, range(10))``,
+but it's more concise and readable.
A list comprehension consists of brackets containing an expression followed
-by a :keyword:`!for` clause, then zero or more :keyword:`!for` or :keyword:`!if`
+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.
+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, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1, 3), (1, 4), (2, 3), (2, 1), (2, 4), (3, 1), (3, 4)]
-and it's equivalent to::
+and it's equivalent to:
>>> combs = []
>>> for x in [1,2,3]:
@@ -283,8 +326,9 @@ List comprehensions can contain complex expressions and nested functions::
>>> [str(round(pi, i)) for i in range(1, 6)]
['3.1', '3.14', '3.142', '3.1416', '3.14159']
+
Nested List Comprehensions
---------------------------
+''''''''''''''''''''''''''
The initial expression in a list comprehension can be any arbitrary expression,
including another list comprehension.
@@ -327,22 +371,23 @@ which, in turn, is the same as::
>>> transposed
[[1, 5, 9], [2, 6, 10], [3, 7, 11], [4, 8, 12]]
+
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::
- >>> list(zip(*matrix))
+ >>> zip(*matrix)
[(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.
.. _tut-del:
-The :keyword:`!del` statement
-=============================
+The :keyword:`del` statement
+============================
There is a way to remove an item from a list given its index instead of its
value: the :keyword:`del` statement. This differs from the :meth:`pop` method
-which returns a value. The :keyword:`!del` statement can also be used to remove
+which returns a value. The :keyword:`del` statement can also be used to remove
slices from a list or clear the entire list (which we did earlier by assignment
of an empty list to the slice). For example::
@@ -435,8 +480,8 @@ The reverse operation is also possible::
>>> x, y, z = t
This is called, appropriately enough, *sequence unpacking* and works for any
-sequence on the right-hand side. Sequence unpacking requires that there are as
-many variables on the left side of the equals sign as there are elements in the
+sequence on the right-hand side. Sequence unpacking requires the list of
+variables on the left to have the same number of elements as the length of the
sequence. Note that multiple assignment is really just a combination of tuple
packing and sequence unpacking.
@@ -457,12 +502,13 @@ empty dictionary, a data structure that we discuss in the next section.
Here is a brief demonstration::
- >>> basket = {'apple', 'orange', 'apple', 'pear', 'orange', 'banana'}
- >>> print(basket) # show that duplicates have been removed
- {'orange', 'banana', 'pear', 'apple'}
- >>> 'orange' in basket # fast membership testing
+ >>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
+ >>> fruit = set(basket) # create a set without duplicates
+ >>> fruit
+ set(['orange', 'pear', 'apple', 'banana'])
+ >>> 'orange' in fruit # fast membership testing
True
- >>> 'crabgrass' in basket
+ >>> 'crabgrass' in fruit
False
>>> # Demonstrate set operations on unique letters from two words
@@ -470,22 +516,22 @@ Here is a brief demonstration::
>>> a = set('abracadabra')
>>> b = set('alacazam')
>>> a # unique letters in a
- {'a', 'r', 'b', 'c', 'd'}
+ set(['a', 'r', 'b', 'c', 'd'])
>>> a - b # letters in a but not in b
- {'r', 'd', 'b'}
- >>> a | b # letters in a or b or both
- {'a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'}
+ set(['r', 'd', 'b'])
+ >>> a | b # letters in either a or b
+ set(['a', 'c', 'r', 'd', 'b', 'm', 'z', 'l'])
>>> a & b # letters in both a and b
- {'a', 'c'}
+ set(['a', 'c'])
>>> a ^ b # letters in a or b but not both
- {'r', 'd', 'b', 'm', 'z', 'l'}
+ set(['r', 'd', 'b', 'm', 'z', 'l'])
Similarly to :ref:`list comprehensions <tut-listcomps>`, set comprehensions
are also supported::
>>> a = {x for x in 'abracadabra' if x not in 'abc'}
>>> a
- {'r', 'd'}
+ set(['r', 'd'])
.. _tut-dictionaries:
@@ -504,7 +550,7 @@ You can't use lists as keys, since lists can be modified in place using index
assignments, slice assignments, or methods like :meth:`append` and
:meth:`extend`.
-It is best to think of a dictionary as a set of *key: value* pairs,
+It is best to think of a dictionary as an unordered set of *key: value* pairs,
with the requirement that the keys are unique (within one dictionary). A pair of
braces creates an empty dictionary: ``{}``. Placing a comma-separated list of
key:value pairs within the braces adds initial key:value pairs to the
@@ -516,9 +562,9 @@ pair with ``del``. If you store using a key that is already in use, the old
value associated with that key is forgotten. It is an error to extract a value
using a non-existent key.
-Performing ``list(d)`` on a dictionary returns a list of all the keys
-used in the dictionary, in insertion order (if you want it sorted, just use
-``sorted(d)`` instead). To check whether a single key is in the
+The :meth:`keys` method of a dictionary object returns a list of all the keys
+used in the dictionary, in arbitrary order (if you want it sorted, just apply
+the :func:`sorted` function to it). To check whether a single key is in the
dictionary, use the :keyword:`in` keyword.
Here is a small example using a dictionary::
@@ -526,27 +572,23 @@ Here is a small example using a dictionary::
>>> tel = {'jack': 4098, 'sape': 4139}
>>> tel['guido'] = 4127
>>> tel
- {'jack': 4098, 'sape': 4139, 'guido': 4127}
+ {'sape': 4139, 'guido': 4127, 'jack': 4098}
>>> tel['jack']
4098
>>> del tel['sape']
>>> tel['irv'] = 4127
>>> tel
- {'jack': 4098, 'guido': 4127, 'irv': 4127}
- >>> list(tel)
- ['jack', 'guido', 'irv']
- >>> sorted(tel)
+ {'guido': 4127, 'irv': 4127, 'jack': 4098}
+ >>> tel.keys()
['guido', 'irv', 'jack']
>>> 'guido' in tel
True
- >>> 'jack' not in tel
- False
The :func:`dict` constructor builds dictionaries directly from sequences of
key-value pairs::
>>> dict([('sape', 4139), ('guido', 4127), ('jack', 4098)])
- {'sape': 4139, 'guido': 4127, 'jack': 4098}
+ {'sape': 4139, 'jack': 4098, 'guido': 4127}
In addition, dict comprehensions can be used to create dictionaries from
arbitrary key and value expressions::
@@ -558,7 +600,7 @@ When the keys are simple strings, it is sometimes easier to specify pairs using
keyword arguments::
>>> dict(sape=4139, guido=4127, jack=4098)
- {'sape': 4139, 'guido': 4127, 'jack': 4098}
+ {'sape': 4139, 'jack': 4098, 'guido': 4127}
.. _tut-loopidioms:
@@ -566,21 +608,11 @@ keyword arguments::
Looping Techniques
==================
-When looping through dictionaries, the key and corresponding value can be
-retrieved at the same time using the :meth:`items` method. ::
-
- >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
- >>> for k, v in knights.items():
- ... print(k, v)
- ...
- gallahad the pure
- robin the brave
-
When looping through a sequence, the position index and corresponding value can
be retrieved at the same time using the :func:`enumerate` function. ::
>>> for i, v in enumerate(['tic', 'tac', 'toe']):
- ... print(i, v)
+ ... print i, v
...
0 tic
1 tac
@@ -592,7 +624,7 @@ with the :func:`zip` function. ::
>>> questions = ['name', 'quest', 'favorite color']
>>> answers = ['lancelot', 'the holy grail', 'blue']
>>> for q, a in zip(questions, answers):
- ... print('What is your {0}? It is {1}.'.format(q, a))
+ ... print 'What is your {0}? It is {1}.'.format(q, a)
...
What is your name? It is lancelot.
What is your quest? It is the holy grail.
@@ -601,8 +633,8 @@ with the :func:`zip` function. ::
To loop over a sequence in reverse, first specify the sequence in a forward
direction and then call the :func:`reversed` function. ::
- >>> for i in reversed(range(1, 10, 2)):
- ... print(i)
+ >>> for i in reversed(xrange(1,10,2)):
+ ... print i
...
9
7
@@ -615,13 +647,23 @@ returns a new sorted list while leaving the source unaltered. ::
>>> basket = ['apple', 'orange', 'apple', 'pear', 'orange', 'banana']
>>> for f in sorted(set(basket)):
- ... print(f)
+ ... print f
...
apple
banana
orange
pear
+When looping through dictionaries, the key and corresponding value can be
+retrieved at the same time using the :meth:`iteritems` method. ::
+
+ >>> knights = {'gallahad': 'the pure', 'robin': 'the brave'}
+ >>> for k, v in knights.iteritems():
+ ... print k, v
+ ...
+ gallahad the pure
+ robin the brave
+
It is sometimes tempting to change a list while you are looping over it;
however, it is often simpler and safer to create a new list instead. ::
@@ -675,27 +717,28 @@ to a variable. For example, ::
>>> non_null
'Trondheim'
-Note that in Python, unlike C, assignment inside expressions must be done
-explicitly with the walrus operator ``:=``. This avoids a common class of
-problems encountered in C programs: typing ``=`` in an expression when ``==``
-was intended.
+Note that in Python, unlike C, assignment cannot occur inside expressions. C
+programmers may grumble about this, but it avoids a common class of problems
+encountered in C programs: typing ``=`` in an expression when ``==`` was
+intended.
.. _tut-comparing:
Comparing Sequences and Other Types
===================================
-Sequence objects typically may be compared to other objects with the same sequence
-type. The comparison uses *lexicographical* ordering: first the first two
-items are compared, and if they differ this determines the outcome of the
-comparison; if they are equal, the next two items are compared, and so on, until
-either sequence is exhausted. If two items to be compared are themselves
-sequences of the same type, the lexicographical comparison is carried out
-recursively. If all items of two sequences compare equal, the sequences are
-considered equal. If one sequence is an initial sub-sequence of the other, the
-shorter sequence is the smaller (lesser) one. Lexicographical ordering for
-strings uses the Unicode code point number to order individual characters.
-Some examples of comparisons between sequences of the same type::
+
+Sequence objects may be compared to other objects with the same sequence type.
+The comparison uses *lexicographical* ordering: first the first two items are
+compared, and if they differ this determines the outcome of the comparison; if
+they are equal, the next two items are compared, and so on, until either
+sequence is exhausted. If two items to be compared are themselves sequences of
+the same type, the lexicographical comparison is carried out recursively. If
+all items of two sequences compare equal, the sequences are considered equal.
+If one sequence is an initial sub-sequence of the other, the shorter sequence is
+the smaller (lesser) one. Lexicographical ordering for strings uses the ASCII
+ordering for individual characters. Some examples of comparisons between
+sequences of the same type::
(1, 2, 3) < (1, 2, 4)
[1, 2, 3] < [1, 2, 4]
@@ -705,14 +748,15 @@ Some examples of comparisons between sequences of the same type::
(1, 2, 3) == (1.0, 2.0, 3.0)
(1, 2, ('aa', 'ab')) < (1, 2, ('abc', 'a'), 4)
-Note that comparing objects of different types with ``<`` or ``>`` is legal
-provided that the objects have appropriate comparison methods. For example,
-mixed numeric types are compared according to their numeric value, so 0 equals
-0.0, etc. Otherwise, rather than providing an arbitrary ordering, the
-interpreter will raise a :exc:`TypeError` exception.
+Note that comparing objects of different types is legal. The outcome is
+deterministic but arbitrary: the types are ordered by their name. Thus, a list
+is always smaller than a string, a string is always smaller than a tuple, etc.
+[#]_ Mixed numeric types are compared according to their numeric value, so 0
+equals 0.0, etc.
.. rubric:: Footnotes
-.. [1] Other languages may return the mutated object, which allows method
- chaining, such as ``d->insert("a")->remove("b")->sort();``.
+.. [#] The rules for comparing objects of different types should not be relied upon;
+ they may change in a future version of the language.
+