Some Remarks about Double/Nested Loops
This post will discuss two additional topics with regard to for loops. In the for loop tutorial, we have briefly shown how a double for loop works, and multiple for loops can be nested in the same manner. Nevertheless, things can get a bit complicated if we want to use break or continue and the results may not be what we want. These two commands only skip the inner loop at the same level but will not affect the outer loop, which will still be carried out. To demonstrate, we can look at this example:
for ii in range(1,10): for jj in range(1,10): x = ii * jj print(x, end=" ") if x >= 40: break print()
The outputs are
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40 6 12 18 24 30 36 42 7 14 21 28 35 42 8 16 24 32 40 9 18 27 36 45
The intention is to stop when \( x \geq 40 \), but perhaps not expected by some people, only the inner loop for jj gets interrupted at the current value of ii, and the outer loop for ii immediately resumes, where ii increases by 1 and a new inner loop for jj is run. So, we say that break (or continue) only exits the current loop. To get the other possibility:
1 2 3 4 5 6 7 8 9 2 4 6 8 10 12 14 16 18 3 6 9 12 15 18 21 24 27 4 8 12 16 20 24 28 32 36 5 10 15 20 25 30 35 40
(We note that both results are reasonable and we may want one way or the other depending on the situation and purpose.) The most common approach is to utilize a flag that stores a True/False boolean value, is triggered inside the inner loop, and later signals the outer loop to terminate as well:
break_flag = Falsefor ii in range(1,10): if break_flag == True: break for jj in range(1,10): x = ii * jj print(x, end=" ") if x >= 40: break_flag = True break print()
Another more Pythonic but also complicated way is to utilize the for-else structure, where the else clause will only be executed if the iteration of the for loop has not been interrupted by a break statement. Then we can combine it with continue to achieve the effect:
for ii in range(1,10): for jj in range(1,10): x = ii * jj print(x, end=" ") if x >= 40: break else: print() continue break
Inside the jj loop, if x never goes above the threshold and break is not met, the else block will be run and continue (which is outside of the inner loop and actually at the same level of the outer loop) will immediately cause the code to jump to the beginning of the next iteration for the outer loop. Otherwise, if x has triggered the break inside the inner loop, then the else part will not be run, and in contrast break in the last line will be subsequently executed and stop the outer loop.
List Comprehension
Often, we need to generate a list containing elements produced from a for loop according to some logic involving repetition or ordering. For example, if we want to make a list with consecutive integers from 1 to 10, a naive way using what we have learnt previously is to first create an empty list and fill in the entries:
my_list = []for kk in range(1,10+1): my_list.append(kk)print(my_list)
This indeed gives [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] without problem. However, there is a Pythonic shorthand for doing this, called list comprehension. Basically, we put a for loop inside the definition of a list so that it will be constructed using the outputs of that for loop. The syntax is [<expression> for <dummy_variable> in <iterable>]. The above case can be written as
my_list = [kk for kk in range(1,10+1)]print(my_list)
and will give the same result. We now demonstrate with one more example, producing the squares of the first 10 odd integers. There are mainly two possible list comprehensions to achieve that:
odd_sq_1 = [kk**2 for kk in range(1,20+1,2)]print(odd_sq_1)odd_sq_2 = [(2*kk-1)**2 for kk in range(1,10+1)]print(odd_sq_2)
Exercise
Recall the function that converts the unit of wind speed from knots to km/h as defined in the exercise from this tutorial. Use list comprehension to output the km/h wind speeds for every 5-knot increment starting from 30 knots to 100 knots.
Suggested Solution
Assuming that the conversion function has been defined as in that tutorial, then it is simply something like
kmh_list = [kts_to_kmh(kt) for kt in range(30,100+1,5)]print(kmh_list)
(How about if we want to round all of them to 1 decimal place?)







Leave a Reply