<jupyter_start><jupyter_text>4. Control flow (Loops and Functions) Control flow is the set of techniques that allows us to manage the way code is executed.For example, you might want to execute some code provided a certain condition is `True`.Or you might want to repeat a certain action a given number of times.Or, again, you might want to run code as long as a condition is `True`, but you do not know how many times the code should be executed before the condition turns `True`.The three examples are managed by the statements [`if`](https://docs.python.org/3/reference/compound_stmts.htmlthe-if-statement), [`for`](https://docs.python.org/3/reference/compound_stmts.htmlthe-for-statement) and [`while`](https://docs.python.org/3/reference/compound_stmts.htmlthe-while-statement).Here we see basic applications, just to convey the idea.We should keep in mind two things when working with control flow statements:- The control flow statement has to be on a line that end with a semicolon (`:`).- The code block following the control flow statements has to be indented with four whitespaces.The `if` and `while` statements work provided that a certain condition holds.Such condition is a boolean value that is either `True` or `False`.Python supports boolean arithmetics with the keywords `and`, `or` and `not`.The `if` statement can be expanded to the `if`-`elif`-`else`.  Loops When working with collections (`lists`, `sets`, `dictionaries`, etc.) it is possibleto operate on every item using a loop.Defining a loop requires an iterable (in our example it is `sample_list`), which could be `list`, `tuple`, `set` or any other object that supports iteration. Byspecifying `item` we are asking python to iterate over one element of the list at a time, storing this element in a variable called `item`. Operations that should be perfomed within the loop must be idented (typically withfour leading spaces, but some use tabs, two spaces, or some other identation). Alsonote the colon `:` at the end of the `for` statement.  **4.1 for** The simplest loop is `for` loop, with the following syntax:```pythonsample_list = [1, 4, 7, 10]for item in sample_list:    print(item)```<jupyter_code>for ... in ...:
    ...
    ...
    ...
sample_list = [1, 4, 7, 10]

for item in sample_list:
    print(item)
name_list = ['Ali', 'Mahshid', 'Javad', 'Yalda']

for name in name_list:
    print('Hi')
    print(name)
print('Bye')
list(range(1,25))
squares = []

for i in range(1,25):
    square = i ** 2
    squares.append(square)

print(squares)
print(list(range(1,25)))<jupyter_output>[1, 4, 9, 16, 25, 36, 49, 64, 81, 100, 121, 144, 169, 196, 225, 256, 289, 324, 361, 400, 441, 484, 529, 576]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24]<jupyter_text>**4.2 while** Python `While` Loop is used to execute a block of statements repeatedly until a given condition is satisfied. And when the condition becomes false, the line immediately after the loop in the program is executed. While loop falls under the category of indefinite iteration. Indefinite iteration means that the number of times the loop is executed isn’t specified explicitly in advance.<jupyter_code>n > 10
n < 10
n = 0

while n < 10:
    print(n)
    n = n + 1  # n += 1
x = 1
while x > 1e-4:  #10 ** (-4):
    print(x)
    x = x / 5<jupyter_output>1
0.2
0.04
0.008
0.0016
0.00032<jupyter_text>**4.3 Conditions** (**if**, **elif**, **else**)  If execution of command should depend on some condition, then we can use `if/else` syntax:```pythonif some_condition:     run code hereelif some_other_condition:     run code hereelse:     run code here```Note that the variables in `if/else` statements should be `Boolean` (True/False), by defaul Pythonwill interpret 0 as False and non-zero as True. Try executing the following:```pythonif 0:    print("A")    if 0.2:    print("B")```<jupyter_code>if 0:
    print("A")

if 0.2:
    print("B")
3 < 2
if 3 < 2:
    print('Hello!')
age = int(input('Enter your age: '))

if age >= 18:
    print('You are old enough to vote!')
else:
    print('You can NOT vote yet!')
age = int(input('Enter your age: '))

if age >= 18:
    print('You are old enough to vote!')
else:
    print('You can NOT vote yet!')
    print("You can will vote after {} years".format(18 - age))
age = int(input('Enter your age: '))

if age < 4:
    price = 0
elif age < 16:
    price = 5
else:
    price = 10
    
print('Your cost is ${}.'.format(price))
my_list = [1,4,7,13,24,123,456,234]

for num in my_list:
    if num % 2 == 0:
        print(num, 'is EVEN number!')
    else:
        print('ODD')<jupyter_output>ODD
4 is EVEN number!
ODD
ODD
24 is EVEN number!
ODD
456 is EVEN number!
234 is EVEN number!<jupyter_text>The break Statement With the `break` statement we can stop the loop even if the while condition is true:```pythoni = 1while i < 6:  print(i)  if i == 3:    break  i += 1```<jupyter_code>i = 1
while i < 6:
    print(i)
    if i == 3:
        break
    i += 1<jupyter_output>1
2
3<jupyter_text>The continue Statement With the `continue` statement we can stop the current iteration, and continue with the next:```pythoni = 0while i < 6:  i += 1   if i == 3:    continue  print(i)```<jupyter_code>i = 0
while i < 6:
    i += 1 
    if i == 3:
        continue
    print(i)<jupyter_output>1
2
4
5
6<jupyter_text>Functions (`def` and `lambda`) You might have noticed so far that Python is rather limited as a programming language.This is because Python is a general-purpose language: it should be flexible enough for everybody to achieve their goals, but it cannot afford to be a BIG library of code.For example, Python does not know what a square root of a number is.While we can always rely on the fact that $\sqrt[n]{x} = x^{1/n}$, it might be useful to define a dedicated function that does the job.In this example, defining a function improves code readability.We can define a new function by using the `def` keyword, listing arguments in round parentheses.Also, if we want the function to give back something, we should explicitly instruct Python to do so with the `return` keyword.<jupyter_code>def test_1():
    ...
    ...
    ...
    print(...)
    return ...
test_1()
def test_2(x, y , z):
    ...
    ...
    ...
    print(...) # return ...
test_2(2,4,123)
def sqrt(x):
    return x ** (1/2)<jupyter_output><empty_output><jupyter_text>Here we defined the square-root function.As it is, this function works for all values of $x$, even negative ones (the result will be a complex number).Again, note that the `def` statement ends with a semicolon (`:`) and any code that belongs to the function is indented with respect to the line containing the keyword `def`.<jupyter_code>sqrt(2)<jupyter_output><empty_output><jupyter_text>An example of a slightly more sophisticated function is one that computes the real roots a (non-negative) number. This function performs the so-called _input validation_.To ensure that the result of $\sqrt[n]{x}$ is a real number, we must ensure that $x$ is non-negative.We do this with an `if` clause and instructing Python to terminate the execution of the function with a `raise` command, which issues an error.Also, the function we defined takes two arguments: `x` and `n`.By specifying `n=2` in the `def` statement, we are saying that the default value of $n$ should be two, but the user can change that value arbitrarily.<jupyter_code>def real_nth_root(x, n = 2):
    if x < 0:
        print('Enter the positive number!')
    else:
        return x ** (1/n)
real_nth_root(2)
real_nth_root(-2)
real_nth_root(8)
real_nth_root(8, 3)
def price():
    age = int(input('Enter your age: '))

    if age < 4:
        price = 0
    elif age < 16:
        price = 5
    else:
        price = 10
        
    print('Your cost is ${}.'.format(price))
price()<jupyter_output>Enter your age: 26
Your cost is $10.<jupyter_text>Finally, a quick-and-dirty way to define functions is by using `lambda` functions, which are also known as [anonymous functions](https://en.wikipedia.org/wiki/Anonymous_function).The inner workings of anonymous functions are quite complicated and we will not cover them.Here it should suffice to know that these functions are defined _in-line_, which means that we do not write a code block for them.Anonymous functions are useful for quick one-liners that do not require much work.We can re-define the function `sqrt` above as an anonymous function.<jupyter_code>root2 = lambda x: x ** (1/2)<jupyter_output><empty_output><jupyter_text>The syntax is as follows.The function `root2` takes an argument `x`, which is indicated right after the keyword `lambda`.There is a semicolon following the statment, after which we find the main task performed by the function we defined.<jupyter_code>root2(5)<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.107284918740766, 'fraction_numerical': 0.031821797931583136, 'mean_word_length': 3.8997772828507795, 'pattern_counts': {'":': 0, '<': 48, '<?xml version=': 0, '>': 39, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 6, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '256207', 'license': 'MIT', 'n_tokens_mistral': 2930, 'n_tokens_neox': 2669, 'n_words': 1202, 'path': 'Natural Resource Economics/.ipynb_checkpoints/02 - Loops python-checkpoint.ipynb', 'repo_name': 'saeed-saffari/Python-for-Economics-fall-2021', 'size': '8799'}