<jupyter_start><jupyter_text>Control Flow: Examples Mastering control flow techniques is fundamental in every programming language.It is the only way we can control how our code is executed.To simplify exposition, we only consider examples that require no module to be imported.  Basic Examples  The `if` statement The `if` statement executes some code conditionally on something being `True`.The following example takes a number and checks whether the remainder of the division `number`÷1 is zero.If this is the case, then the number is an integer; otherwise the number is not an integer (can be either rational or irrational).Checking whether a number is rational or irrational with a computer turns out to be troublesome...<jupyter_code>number = 2

if number % 1 == 0:
    print('The number is an integer.')
else:
    print('The number is not an integer (a real?).')<jupyter_output>The number is an integer.<jupyter_text>We can also define various cases using the `if`...`elif`...`else` paradigm.<jupyter_code>number = 17

if number % 2 == 0:
    print('The number is a multiple of 2.')
elif number % 3 == 0:
    print('The number is a multiple of 3, but not of 2.')
elif number % 5 == 0:
    print('The number is a multiple of 5, but not of 2 or of 3.')
else:
    print('The number is a multiple of neither 2, 3 nor 5.')<jupyter_output>The number is a multiple of neither 2, 3 nor 5.<jupyter_text>The `for` loop A `for` loop repeats some code a predefined number of times.In the example that follows, we are going to create an empty list, then add the first 10 integers to it.<jupyter_code>a = []
for i in range(10):
    a.append(i+1)
    print(a)<jupyter_output>[1]
[1, 2]
[1, 2, 3]
[1, 2, 3, 4]
[1, 2, 3, 4, 5]
[1, 2, 3, 4, 5, 6]
[1, 2, 3, 4, 5, 6, 7]
[1, 2, 3, 4, 5, 6, 7, 8]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]<jupyter_text>The `while` loop The `while` loop repeats some code provided some condition occurs.This is useful if we want to repeat the code, but we do not know how many times the repetition is required in order to achieve a result.In the example that follows, we reconstruct the Fibonacci sequence up until its `n`th element.We use the `while` loop to check the length of the sequence we build.As soon as we obtain the required length, we stop the code.<jupyter_code>max_length = 15
fibonacci = [0, 1]

while len(fibonacci) < max_length:
    next_element = fibonacci[-2] + fibonacci[-1]
    fibonacci.append(next_element)

print(fibonacci)<jupyter_output>[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377]<jupyter_text>The `break` statement The `break` statement allows the code to interrupt a loop (typically, a `for` or a `while` loop).We normally issue this statement after checking some condition.A trivial example follows.We start a `while` loop with a constant condition `True`.This makes the `while` loop run indefinitely, which is not nice for your computer.However, we can check for the number of times the loop repeats.If such number is "too high" (according to an arbitrary criterion), then we can safely assume something went wrong and we stop the loop.<jupyter_code>iteration_no = 0
max_iter = 1000000

while True:
    iteration_no += 1
    if iteration_no > max_iter:
        print('Iteration "max_iter" {} reached. Stopping the loop.'.format(max_iter))
        break<jupyter_output>Iteration "max_iter" 1000000 reached. Stopping the loop.<jupyter_text>The `continue` statement The `continue` statement instructs a `for` or `while` loop to skip the remaining code block and proceed to the next iteration (if any).This is useful if, in a loop, we encounter some special case and we do not require the rest of the code to run in that case.In the example that follows, we loop on the first 10 integers and we check whether they are multiple of 3.If so, then we display some text.Otherwise, we display another text.Note that, every time we hit a multiple of three, whatever is in the loop after the `continue` statement is not executed.<jupyter_code>for i in range(1, 10):
    if i % 3 == 0:
        print('Found a multiple of three: {}.'.format(i))
        continue
    print('Keeping on searching...')<jupyter_output>Keeping on searching...
Keeping on searching...
Found a multiple of three: 3.
Keeping on searching...
Keeping on searching...
Found a multiple of three: 6.
Keeping on searching...
Keeping on searching...
Found a multiple of three: 9.<jupyter_text>Mastering Control Flow The following examples take control flow statements and combines them.Many algorithms in Economics (and not only) take advantage of this.  Compute Euler's constant $e$To this end, consider that we can define $e$ as$$e := \lim_{n \to \infty} {\left( 1 + \frac{1}{n} \right)}^{n}$$What we do below is to compute the argument of the limit for a given value `n`.Then, we compute the same value for `n+1`.We check whether the improvement to the approximation of Euler's constant is "big enough", in the sense that it is above a certain "tolerance" threshold.If the improvement is big enough, then we move on to `n+2`.Otherwise we interrupt the algorithm and check the result.<jupyter_code># Starting conditions, just to get the loop started
improvement = 1.0
tolerance = 1e-10  # 10^(-10)
n = 1
step_increase = 1
results = [1.0]
iteration_no = 0

# Here is the iterative algorithm to obtain e
while improvement > tolerance:           # as long as we improve significantly
    tentative = ( 1 + (1 / n) ) ** n     # compute a tentative result
    results.append( tentative )          # store result in a list
    improvement = abs( results[-1] - results[-2] )  # check the improvement
    n += step_increase                   # increase this value
    iteration_no += 1                    # increase the iteration counter
    
# Print results to obtain information about the algorithm
print("This code ran " + str(iteration_no) + " times.")
print("The approximated Euler's constant is " + str(results[-1]) + ".")<jupyter_output>This code ran 94760 times.
The approximated Euler's constant is 2.7182674855879516.<jupyter_text>Try running the code above changing `step_increase` to another integer value, such as `10`.The number of times the code will run will change.This is why we need a `while` loop: we cannot know a priori how many iterations we need.  List the first 10 prime numbersIn this example we list the first 10 prime numbers, including 0 and 1.We proceed as follows.We consider a candidate, starting from the number 2.For this candidate, we check whether all numbers between 2 and itself is a divisor.As soon as we find a divisor of the candidate, we stop searching for divisors, we discard the current candidate and we move to the next one.If we find no divisors for a candidate, then we confirm we found a prime number and we add it to the list of results.The latter case is captured with an `else` statement to the `for` loop.This specifies what we have to do in case we did not break the `for` loop.This use of `else` also works within a `while` loop.Note that the use of break here allows for performance improvements: we do not need to find all divisors for a candidate number, we just need to find one in order to reject the candidate as a prime number.<jupyter_code>primes = [0, 1]
not_primes = []
candidate = primes[-1] + 1

while len(primes) < 10:
    for divisor in range(2, candidate):
        if candidate % divisor == 0:
            not_primes.append(candidate)
            break  # exits the 'for' loop and moves on to the next value of 'divisor'
    else:          # specifies what happens if we never break the 'for' loop
        primes.append(candidate)
    candidate += 1  # go on with the next integer

print('Prime numbers: ' + str(primes))
print('Non-prime numbers: ' + str(not_primes))<jupyter_output>Prime numbers: [0, 1, 2, 3, 5, 7, 11, 13, 17, 19]
Non-prime numbers: [4, 6, 8, 9, 10, 12, 14, 15, 16, 18]
{'fraction_non_alphanumeric': 0.0861128725428028, 'fraction_numerical': 0.030310716550412176, 'mean_word_length': 3.8739184177997528, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 27, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 2, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '8', 'dir': 'jupyter-structured-clean-dedup', 'id': '406577', 'license': 'MIT', 'n_tokens_mistral': 2504, 'n_tokens_neox': 2242, 'n_words': 1167, 'path': 'examples/control_flow.ipynb', 'repo_name': 'AndreaPasqualini/intro_to_python_with_networks', 'size': '7885'}