02.02 - MORE PYTHON

!wget --no-cache -O init.py -q https://raw.githubusercontent.com/rramosp/ai4eng.v1/main/content/init.py
import init; init.init(force_download=False); init.get_weblink()
import numpy as np

Functions

Recall that Python is an indented language. It does not uses any kind of brakets to delimit the scope of programming structures, which are signaled by changes in indentation

Arguments types are not declared, implementation must be prepared to deal with the data types you want

def f1(a,b):
    r = a*2
    return r+b
    
def gt(a,b):
    if a>b:
        return a
    else:
        return b
f1(2,3)
7
f1(['hola', 2], [3])
['hola', 2, 'hola', 2, 3]
f1('pepe', 'gotera')
'pepepepegotera'
gt(3,4)
4
gt("hola","adios")
'hola'

functions can have default values

def f_power(x, p=2):
    return x**p

f_power(3)
9
f_power(3,2)
9

args can be named when calling the function and, if so, any order is ok

f_power(p=2, x=3)
9

functions can have functions defined within, but they are only visible inside the function

def f(a,b):
    def squared(x):
        return x**2
    return squared(a+b)
f(2,3)
25
squared(3)
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-22-6fadce67701d> in <module>
----> 1 squared(3)

NameError: name 'squared' is not defined

functions are regular python objects which can be passed around

def apply_if_int(f, x):
    if type(x)==int:
        return f(x)
    
    return x
def cubed(x):
    return x**3
apply_if_int(cubed, 3)
27
apply_if_int(cubed, 3.)
3.0

map exploits this

map(cubed, [10,20,3,-2,9])
<map at 0x7fa8f84f8c10>
list(map(cubed, [10,20,3,-2,9]))
[1000, 8000, 27, -8, 729]

lambda functions are like constants

list(map(lambda x: x**2, [10,20,3,-2,9]))
[100, 400, 9, 4, 81]

and can even be used to define simple functions

sqrd = lambda x: x**2
sqrd(8)
64
list(map(sqrd, [10,20,3,-2,9]))
[100, 400, 9, 4, 81]

Exceptions

catching

int(3.2)
3
int("hola")
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-48-62025142aa33> in <module>
----> 1 int("hola")

ValueError: invalid literal for int() with base 10: 'hola'
def int_times_two(x):
    try:
        return(int(x)*2)
    except ValueError:
        return 0
int_times_two(2)
4
int_times_two(2.5)
4
int_times_two("hola")
0

raising

def get_positive_integer_from_user():
    a = int(input("Enter a positive integer: "))
    if a <= 0:
        raise ValueError("That is not a positive number!")
    print ("thanks!")
get_positive_integer_from_user()
Enter a positive integer: 3
thanks!
get_positive_integer_from_user()
Enter a positive integer: -1
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-57-ea5635cae962> in <module>
----> 1 get_positive_integer_from_user()

<ipython-input-55-a7d1640efb92> in get_positive_integer_from_user()
      2     a = int(input("Enter a positive integer: "))
      3     if a <= 0:
----> 4         raise ValueError("That is not a positive number!")
      5     print ("thanks!")

ValueError: That is not a positive number!

Comprehensions

IF

a=15
if a > 10:
    s = "mayor que 10"
else:
    s = "menor que 10"

print(s)
mayor que 10
a = 5
s = "mayor que 10" if a > 10 else "menor que 10"
print(s)
menor que 10

FOR

b = [1,10, 20.5, "hola", 10.4, 12]
r = []
for i in b:
    r.append(int_times_two(i))
r
[2, 20, 40, 0, 20, 24]
r = [int_times_two(i) for i in b]
r
[2, 20, 40, 0, 20, 24]

FOR / IF filter

r = [int_times_two(i) for i in b if type(i)!=int or i > 10]
r
[40, 0, 20, 24]

DICT

r = {i: int_times_two(i) for i in b if type(i)!=int or i > 10}
r
{20.5: 40, 'hola': 0, 10.4: 20, 12: 24}
r['hola']
0