Idiomatic loops¶

Looping in general¶

In [1]:
data = ["John", "Doe", "was", "here"] 

Don't do it like this. While loops are actually really rarely needed.

In [2]:
idx = 0 while idx < len(data): print(data[idx]) idx += 1 
John Doe was here 

Don't do like this either.

In [3]:
for idx in range(len(data)): print(data[idx]) 
John Doe was here 

Do it like this!¶

In [4]:
for item in data: print(item) 
John Doe was here 

If you need the index as well, you can use enumerate.

In [5]:
for idx, val in enumerate(data): print(f"{idx}: {val}") 
0: John 1: Doe 2: was 3: here 

Looping over a range of numbers¶

Don't do this.

In [6]:
i = 0 while i < 6: print(i) i += 1 
0 1 2 3 4 5 

Don't do this either.

In [7]:
for val in [0, 1, 2, 3, 4, 5]: print(val) 
0 1 2 3 4 5 

Do it like this!¶

In [8]:
for val in range(6): print(val) 
0 1 2 3 4 5 

Reversed looping¶

In [9]:
data = ["first", "to", "last", "from"] 

This is no good.

In [10]:
i = len(data) - 1 while i >= 0: print(data[i]) i -= 1 
from last to first 

Do it like this!¶

In [11]:
for item in reversed(data): print(item) 
from last to first 

Looping over n collections simultaneously¶

In [12]:
collection1 = ["a", "b", "c"] collection2 = (10, 20, 30, 40, 50) collection3 = ["John", "Doe", True] 

Oh boy, not like this.

In [13]:
shortest = len(collection1) if len(collection2) < shortest: shortest = len(collection2) if len(collection3) < shortest: shortest = len(collection3) i = 0 while i < shortest: print(collection1[i], collection2[i], collection3[i]) i += 1 
a 10 John b 20 Doe c 30 True 

This is getting better but there's even a better way!

In [14]:
shortest = min(len(collection1), len(collection2), len(collection3)) for i in range(shortest): print(collection1[i], collection2[i], collection3[i]) 
a 10 John b 20 Doe c 30 True 

Do it like this!¶

In [15]:
for first, second, third in zip(collection1, collection2, collection3): print(first, second, third) 
a 10 John b 20 Doe c 30 True 

You can also create a dict out of two collections!

In [16]:
my_dict = dict(zip(collection1, collection2)) print(my_dict) 
{'a': 10, 'b': 20, 'c': 30} 

for - else - Checking for a match in a collection¶

Let's say we want to verify a certain condition is met by at least one element in a collection. Let's consider the following relatively naive example where we want to verify that at least one item is "python" (case insensitive) in data. If not, we'll raise a ValueError.

In [17]:
data = [1, 2, 3, "This", "is", "just", "a", "random", "Python", "list"] 

Don't do it like this

In [18]:
found = False for val in data: if str(val).lower() == "python": found = True break if not found: raise ValueError("Nope, couldn't find.") 

Do it like this!¶

In [19]:
for val in data: if str(val).lower() == "python": break else: raise ValueError("Nope, couldn't find.")