<jupyter_start><jupyter_text>All of these python notebooks are available at [https://github.com/caxqueiroz/coding-with-python]  Control Flow StatementsThe key thing to note about Python's control flow statements and program structure is that it uses _indentation_ to mark blocks. Hence the amount of white space (space or tab characters) at the start of a line is very important. This generally helps to make code more readable but can catch out new users of python.  Conditionals If ```pythonif some_condition:    code block```<jupyter_code>x = 12
if x > 10:
    print("Hello")<jupyter_output>Hello<jupyter_text>If-else ```pythonif some_condition:    algorithmelse:    algorithm```<jupyter_code>x = 12
if 10 < x < 11:
    print("hello")
else:
    print("world")<jupyter_output>world<jupyter_text>Else if ```pythonif some_condition:      algorithmelif some_condition:    algorithmelse:    algorithm```<jupyter_code>x = 10
y = 12
if x > y:
    print("x>y")
elif x < y:
    print("x<y")
else:
    print("x=y")<jupyter_output>x<y<jupyter_text>if statement inside a if statement or if-elif or if-else are called as nested if statements.<jupyter_code>x = 10
y = 12
if x > y:
    print( "x>y")
elif x < y:
    print( "x<y")
    if x==10:
        print ("x=10")
    else:
        print ("invalid")
else:
    print ("x=y")<jupyter_output>x<y
x=10<jupyter_text>Loops  For ```pythonfor variable in something:    algorithm```    When looping over integers the **range()** function is useful which generates a range of integers:* range(n) =  0, 1, ..., n-1* range(m,n)= m, m+1, ..., n-1* range(m,n,s)= m, m+s, m+2s, ..., m + ((n-m-1)//s) * s<jupyter_code>for ch in 'abc':
    print(ch)
total = 0
for i in range(5):
    total += i
for i,j in [(1,2),(3,1)]:
    total += i**j
print("total =",total)<jupyter_output>a
b
c
total = 14<jupyter_text>In the above example, i iterates over the 0,1,2,3,4. Every time it takes each value and executes the algorithm inside the loop. It is also possible to iterate over a nested list illustrated below.<jupyter_code>list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
for list1 in list_of_lists:
        print(list1)<jupyter_output>[1, 2, 3]
[4, 5, 6]
[7, 8, 9]<jupyter_text>A use case of a nested for loop in this case would be,<jupyter_code>list_of_lists = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
total=0
for list1 in list_of_lists:
    for x in list1:
        total = total+x
print(total)<jupyter_output>45<jupyter_text>There are many helper functions that make **for** loops even more powerful and easy to use. For example **enumerate()**, **zip()**, **sorted()**, **reversed()**<jupyter_code>print("reversed: ",end="")
for ch in reversed("abc"):
    print(ch,end=";")
print("\nenuemerated: ")
for i,ch in enumerate("abc"):
    print(i,"=",ch,end="; ")
print("\nzip'ed: ")
for a,x in zip("abc","xyz"):
    print(a,":",x)<jupyter_output>reversed: c;b;a;
enuemerated: 
0 = a; 1 = b; 2 = c; 
zip'ed: 
a : x
b : y
c : z<jupyter_text>While ```pythonwhile some_condition:      algorithm```<jupyter_code>i = 1
while i < 3:
    print(i ** 2)
    i = i+1
print('Bye')<jupyter_output>1
4
Bye<jupyter_text>Break As the name says. It is used to break out of a loop when a condition becomes true when executing the loop.<jupyter_code>for i in range(100):
    print(i)
    if i>=7:
        break<jupyter_output>0
1
2
3
4
5
6
7<jupyter_text>Continue This continues the rest of the loop. Sometimes when a condition is satisfied there are chances of the loop getting terminated. This can be avoided using continue statement.<jupyter_code>for i in range(10):
    if i>4:
        print("Ignored",i)
        continue
    # this statement is not reach if i > 4
    print("Processed",i)<jupyter_output>Processed 0
Processed 1
Processed 2
Processed 3
Processed 4
Ignored 5
Ignored 6
Ignored 7
Ignored 8
Ignored 9<jupyter_text>Catching exceptions To break out of deeply nested exectution sometimes it is useful to raise an exception.A try block allows you to catch exceptions that happen anywhere during the exeuction of the try block:```pythontry:    codeexcept  as :     deal with error of this typeexcept:     deal with any error```<jupyter_code>try:
    count=0
    while True:
        while True:
            while True:
                print("Looping")
                count = count + 1
                if count > 3:
                    raise Exception("abort") # exit every loop or function
except Exception as e: # this is where we go when an exception is raised
    print("Caught exception:",e)<jupyter_output>Looping
Looping
Looping
Looping
Caught exception: abort<jupyter_text>This can also be useful to handle unexpected system errors more gracefully:<jupyter_code>try:
    for i in [2,1.5,0.0,3]:
        inverse = 1.0/i
except: # no matter what exception
    print("Cannot calculate inverse")<jupyter_output>Cannot calculate inverse
{'fraction_non_alphanumeric': 0.12143742255266418, 'fraction_numerical': 0.02560925237505163, 'mean_word_length': 3.8673366834170855, 'pattern_counts': {'":': 1, '<': 49, '<?xml version=': 0, '>': 49, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '13', 'dir': 'jupyter-structured-clean-dedup', 'id': '98546', 'license': 'CC-BY-3.0', 'n_tokens_mistral': 1759, 'n_tokens_neox': 1658, 'n_words': 579, 'path': 'control_flow_statements.ipynb', 'repo_name': 'caxqueiroz/coding-with-python', 'size': '4842'}