diff --git a/Doc/tutorial/controlflow.rst b/Doc/tutorial/controlflow.rst index 6a9bb48..7b7a9df 100644 --- a/Doc/tutorial/controlflow.rst +++ b/Doc/tutorial/controlflow.rst @@ -39,18 +39,19 @@ to avoid excessive indentation. An :keyword:`if` ... :keyword:`elif` ... .. _tut-for: -:keyword:`for` Statements -========================= +:keyword:`for` Loops +==================== .. index:: statement: for -The :keyword:`for` statement in Python differs a bit from what you may be used -to in C or Pascal. Rather than always iterating over an arithmetic progression -of numbers (like in Pascal), or giving the user the ability to define both the -iteration step and halting condition (as C), Python's :keyword:`for` statement -iterates over the items of any sequence (a list or a string), in the order that -they appear in the sequence. For example (no pun intended): +Python :keyword:`for` loops let you obtain and work with successive items from +an :term:`iterable` object until that object's supply of items is exhausted. +:term:`Iterable` objects in Python include :term:`sequence` types like lists +and strings, and their items are said to be iterated over in the loop. + +The following example iterates over the (string) items of a list printing the +current string and its length at each iteration: .. One suggestion was to give a real C example here, but that may only serve to confuse non-C programmers. @@ -66,29 +67,13 @@ they appear in the sequence. For example (no pun intended): window 6 defenestrate 12 -If you need to modify the sequence you are iterating over while inside the loop -(for example to duplicate selected items), it is recommended that you first -make a copy. Iterating over a sequence does not implicitly make a copy. The -slice notation makes this especially convenient:: - - >>> for w in words[:]: # Loop over a slice copy of the entire list. - ... if len(w) > 6: - ... words.insert(0, w) - ... - >>> words - ['defenestrate', 'cat', 'window', 'defenestrate'] - -With ``for w in words:``, the example would attempt to create an infinite list, -inserting ``defenestrate`` over and over again. - +Python :keyword:`for` loops differ from what you may be used to from Pascal or +C, in which for loops are iterating over an arithmetic progression of numbers, +or giving the user the ability to define both the iteration step and halting +condition, respectively. -.. _tut-range: - -The :func:`range` Function -========================== - -If you do need to iterate over a sequence of numbers, the built-in function -:func:`range` comes in handy. It generates arithmetic progressions:: +If you do want a :keyword:`for` loop to iterate over a progression of numbers, +in Python, you should use a *range*, for example:: >>> for i in range(5): ... print(i) @@ -99,57 +84,17 @@ If you do need to iterate over a sequence of numbers, the built-in function 3 4 -The given end point is never part of the generated sequence; ``range(10)`` generates -10 values, the legal indices for items of a sequence of length 10. It -is possible to let the range start at another number, or to specify a different -increment (even negative; sometimes this is called the 'step'):: - - range(5, 10) - 5 through 9 +.. seealso:: - range(0, 10, 3) - 0, 3, 6, 9 + :ref:`typesseq-range` + Ranges are an elegant and memory-efficient way to generate arithmetic + progressions of numbers on demand. - range(-10, -100, -30) - -10, -40, -70 - -To iterate over the indices of a sequence, you can combine :func:`range` and -:func:`len` as follows:: - - >>> a = ['Mary', 'had', 'a', 'little', 'lamb'] - >>> for i in range(len(a)): - ... print(i, a[i]) - ... - 0 Mary - 1 had - 2 a - 3 little - 4 lamb - -In most such cases, however, it is convenient to use the :func:`enumerate` -function, see :ref:`tut-loopidioms`. - -A strange thing happens if you just print a range:: - - >>> print(range(10)) - range(0, 10) - -In many ways the object returned by :func:`range` behaves as if it is a list, -but in fact it isn't. It is an object which returns the successive items of -the desired sequence when you iterate over it, but it doesn't really make -the list, thus saving space. - -We say such an object is *iterable*, that is, suitable as a target for -functions and constructs that expect something from which they can -obtain successive items until the supply is exhausted. We have seen that -the :keyword:`for` statement is such an *iterator*. The function :func:`list` -is another; it creates lists from iterables:: - - - >>> list(range(5)) - [0, 1, 2, 3, 4] - -Later we will see more functions that return iterables and take iterables as argument. +While it is possible to combine :func:`range` and :func:`len` to iterate over +the indices of a sequence, it is usually preferable to use the built-in +:func:`enumerate` function for this purpose. See :ref:`tut-loopidioms` for an +illustration of this and other issues (like modifying a list while iterating +over its items) related to the use of :keyword:`for` loops. .. _tut-break: @@ -161,9 +106,9 @@ The :keyword:`break` statement, like in C, breaks out of the smallest enclosing :keyword:`for` or :keyword:`while` loop. Loop statements may have an ``else`` clause; it is executed when the loop -terminates through exhaustion of the list (with :keyword:`for`) or when the -condition becomes false (with :keyword:`while`), but not when the loop is -terminated by a :keyword:`break` statement. This is exemplified by the +terminates through exhaustion of the :term:`iterable` (with :keyword:`for`) +or when the condition becomes false (with :keyword:`while`), but not when the +loop is terminated by a :keyword:`break` statement. This is exemplified by the following loop, which searches for prime numbers:: >>> for n in range(2, 10): @@ -188,10 +133,10 @@ following loop, which searches for prime numbers:: the :keyword:`for` loop, **not** the :keyword:`if` statement.) When used with a loop, the ``else`` clause has more in common with the -``else`` clause of a :keyword:`try` statement than it does that of +``else`` clause of a :keyword:`try` statement than it does with that of :keyword:`if` statements: a :keyword:`try` statement's ``else`` clause runs when no exception occurs, and a loop's ``else`` clause runs when no ``break`` -occurs. For more on the :keyword:`try` statement and exceptions, see +occurs. For more on the :keyword:`try` statement and exceptions, see :ref:`tut-handling`. The :keyword:`continue` statement, also borrowed from C, continues with the next @@ -759,3 +704,4 @@ extracted for you: .. [#] Actually, *call by object reference* would be a better description, since if a mutable object is passed, the caller will see any changes the callee makes to it (items inserted into a list). + diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index 6140ece..ec8200c 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -616,7 +616,7 @@ returns a new sorted list while leaving the source unaltered. :: pear 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. :: +however, it is often simpler and safer to create a new list, :: >>> import math >>> raw_data = [56.2, float('NaN'), 51.7, 55.3, 52.5, float('NaN'), 47.8] @@ -628,6 +628,20 @@ however, it is often simpler and safer to create a new list instead. :: >>> filtered_data [56.2, 51.7, 55.3, 52.5, 47.8] +or to iterate over a copy of the list instead (the slice notation makes this +especially convenient):: + + >>> words = ['cat', 'window', 'defenestrate'] + >>> for w in words[:]: # Loop over a slice copy of the entire list. + ... if len(w) > 6: + ... words.insert(0, w) + ... + >>> words + ['defenestrate', 'cat', 'window', 'defenestrate'] + +With ``for w in words:`` the last example would attempt to create an infinite +list, inserting ``defenestrate`` over and over again. + .. _tut-conditions: