===== Loops ===== Loops are a powerful building block for writing programs. They make it possible to write programs that perform repeated work, without having to make copies of the same instructions (lines of code). Loops also make programs easier to read and maintain. They enable us to decide how many times to iterate while a program is running (for instance, based on a calculation or something the user enters), rather than at the time we wrote the program. In fact, it would be impossible to write most programs without loops. .. _basics: **Basics** The most basic loop in Python is the for-each loop: .. code:: for in The expression must yield a value, such as a list or a string, that can be iterated over. We will explain this construct using lists to start. Each iteration through the loop, the variable () takes on a value from the list starting at index 0 and proceeding in order. Here is an example loop: .. code:: In [63]: for y in l1: ....: print("y = " + str(y)) ....: y = 1 y = abc y = 5.7 y = [1, 27.0, 5] y = 27 Please note that ``...:`` is the prompt that iPython uses when a piece of code is spread over multiple lines. It is not part of the syntax of the for loop. .. _append: **Combining loops and append** It is very common to use loops to create new list from an existing list. For example, here is code that generates a new list (``nl``) in which the ith element of the new list is the square of the ith element of a list ``l``. .. code:: In [64]: nl = [] ....: for x in l: ....: nl.append(x*x) The variable ``nl`` initially refers to an empty list. Every time around the loop a new entry is added to the list. .. _range: **Range** At times it is useful to iterate over the index space for a list (0, 1, ..., N-1) rather than iterating over the contents of the list. The ``range`` function is useful for this purpose. In earlier versions of Python, the ``range`` function produced a list. In Python 3, ``range`` yields an object that produces a sequence of integers as needed. It can be used in three ways: - ``range(ub)`` which yields an object that produces a sequence of consecutive integer values from 0 up to but not incuding the upper bound ``ub`` - ``range(lb, ub)`` which yields an object that produces a sequence of consecutive integer values from starting at the lower bound ``lb`` up to but not incuding the upper bound ``ub``. - ``range(lb, ub, incr)`` which yields an object that produces a sequence of integer values from starting at the lower bound ``lb`` up to but not incuding the upper bound ``ub``, increments of of size ``incr``. .. _index_space: **Iterating over the index space of a loop** An alternate way of iterating over a list is by iterating over the index space of a list ``l`` using the expression ``range(len(l))``. For example, we could rewrite the example above as: .. code:: In [75]: for i in range(len(l1)): y = l[i] print("y = " + str(y)) ....: y = 1 y = abc y = 5.7 y = [1, 27.0, 5] y = 27 This style of iterating over lists is common in other languages, but less common in Python, where iterating as described in basics_ is more common.