Loops are an integral part of any programming language and one of your most powerful assets to manipulate control flow. Loops allow you to repeat actions any number of times with very concise syntax. If loops didn't exist, you would have to copy, paste, and possibly adjust all the statements you would want repeated. Python provides two structures that support looping, the #\mathtt{\color{#8959A8} {\text{for}}}# loop and the #\mathtt{\color{#8959A8} {\text{while}}}# loop.
Unlike other programming languages, where a #\color{#8959A8} {\mathtt{\text{for}}}# loop is often step-based, a #\color{#8959A8} {\mathtt{\text{for}}}# loop in Python iterates through the elements of an iterable object.
An iterable is any object capable of returning its members one at a time, permitting it to be iterated over.
An iterable object is any object that supports the #\mathtt{\color{#4271ae}{\text{__getitem__}}\text{()}}# or #\mathtt{\color{#4271ae}{\text{__iter__}}\text{()}}# method, which are the methods that are called when you try to iterate over an object.
>>> '__iter__' in dir(str)
|
True
|
>>> '__iter__' in dir(int)
|
False
|
The #\mathtt{\color{#4271ae} {\text{dir}}\text{(}\textit{obj}\text{)}}# function returns the names of all methods defined by obj. In the code above we check whether the #\mathtt{\color{#4271ae}{\text{str}}}# and #\mathtt{\color{#4271ae}{\text{int}}}# objects support the #\mathtt{\color{#4271ae}{\text{__iter__}}\text{()}}# method. As you can see, strings are iterable objects, while integers are not. In fact, strings are the only iterables we've discussed thus far.
So how does one loop through an iterable using a #\color{#8959A8} {\mathtt{\text{for}}}# loop? The syntax is actually very intuitive.
#\begin{split}
\color{#8959A8} {\mathtt{for}} \textit{ } & \textit{member } \color{#8959A8} {\mathtt{in}} \textit{ iterable}\mathtt{:}\\
& \textit{statement}\\
\end{split}#
Here, member is the object that the iterable returns at every iteration of the loop. The indented statement is the code that is ran every iteration. The reference to member can be used in the statement, and as mentioned, is updated to the next member every iteration.
For example, when iterating over the #\mathtt{\color{#4271ae} {\text{str}}}# object #\mathtt{\color{#718c00} {\text{"abc"}}}#, member will first be a reference to #\mathtt{\color{#718c00} {\text{"a"}}}#, then to #\mathtt{\color{#718c00}{\text{"b"}}}#, and in the final iteration to #\mathtt{\color{#718c00}{\text{"c"}}}#.
|
|
iterable = "abc"
for member in iterable: print(member)
|
a b c
|
|
#\color{#8959A8} {\mathtt{\text{for}}}# loops also support a manual break with the #\color{#8959A8}{\mathtt{\text{break}}}# keyword, usually used in combination with a conditional statement.
#\color{#8959A8}{\mathtt{\text{for}}}# loops can also be combined with the #\color{#8959A8}{\mathtt{\text{else}}}# keyword. The #\color{#8959A8}{\mathtt{\text{else}}}# block is only executed when the loop is completely exhausted. In other words, when #\color{#8959A8}{\mathtt{\text{break}}}# is not triggered prematurely. If there's no conditional break present in the for loop, an else-statement can still be used for readability.
|
|
string = "Hello, world! How have you been?"
for char in string: print(char, end="")
if char in "!?.": break else: print("No sentence.")
|
Hello, world!
|
|
#\color{#8959A8} {\mathtt{\text{for}}}# loops also support the #\color{#8959A8} {\mathtt{\text{continue}}}# keyword. #\color{#8959A8} {\mathtt{\text{continue}}}# allows you to jump to the next iteration of the loop when it is triggered. When a conditional statement containing #\color{#8959A8} {\mathtt{\text{continue}}}# is triggered, all subsequent code will be skipped over.
|
|
for char in "abcDEF": if not char.isupper(): continue print(char)
|
D E F
|
|
Now that we have seen the syntax of a for loop, we need to introduce more iterable objects. For now, we'll do so using functions that return iterable objects. The #\color{#4271ae} {\mathtt{\text{range}}}# function is the most common iterable generating function and mimicks a traditional #\color{#8959A8} {\mathtt{\text{for}}}# loop.
#\color{#4271ae} {\mathtt{range}}([\textit{start}], \textit{stop}, [\textit{step}])#
The #\color{#4271ae} {\mathtt{\text{range}}}# function returns an iterable exclusive range from start to stop. The start argument is optional, if left undefined, the range will always start at #\color{#F5871F} {\mathtt{\text{0}}}#. An additional, also optional argument, is step, it defines the increment between members of the range, the default is #\color{#F5871F} {\mathtt{\text{1}}}#. All arguments of the #\color{#4271ae} {\mathtt{\text{range}}}# function have to be of type #\color{#4271ae} {\mathtt{\text{int}}}#.
|
|
for i in range(5): print(i)
|
0 1 2 3 4
|
|
#\color{#4271ae} {\mathtt{enumerate}}(\textit{iterable}, [\textit{start}])#
The #\color{#4271ae} {\mathtt{\text{enumerate}}}# function returns an iterable exclusive range from start to the length of the corresponding iterable, and the iterable itself. The default value for the optional start argument is #\color{#F5871F} {\mathtt{\text{0}}}#. Note that we loop through two members at a time now, the member of the range #\mathtt{\text{i}}# and the member of the iterable #\mathtt{\text{char}}#. #\color{#4271ae} {\mathtt{\text{enumerate}}}# allows you to loop over an iterable and a potentially corresponding number or index.
|
|
for i, char in enumerate("abc"): print(i, char)
|
0 a 1 b 2 c
|
|
#\color{#4271ae} {\mathtt{zip}}(\textit{iterable}_\textit{1}, \textit{iterable}_\text{2}, \dots)#
The #\color{#4271ae} {\mathtt{\text{zip}}}# function returns a combined iterable formed by the iterators referenced in its arguments. Like #\color{#4271ae} {\mathtt{\text{enumerate}}}#, we can now loop through multiple members per iteration. Only iterables of the same length can be combined using #\color{#4271ae} {\mathtt{\text{zip}}}#.
|
|
seq = zip("abc", "def", "ghi")
for c1, c2, c3 in seq: print(c1, c2, c3)
|
a d g b e h c f i
|
|
In the next chapter, we will see more iterable datatypes.