02.01 - BASIC STRUCTURES

!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()

Introduction to Python

Python is interpreted and dynamically typed. Observe in the following lines:

  • variables a and b have specific data types even if they are not explicitly defined.

  • python guesses their types by how they are being used (\\ is integer division, while \ is floating point division)

  • python keeps executing stuff while no error is found \(\rightarrow\) python is interpreted

a = 4
print (a, type(a))
4 <class 'int'>
b = 9.
print (a, type(b))
4 <class 'float'>
c = 9/4
print (c, type(c))
2.25 <class 'float'>
d = 9//4
print (d, type(d))
print (x)
2 <class 'int'>
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-4-35e15d72124c> in <module>
      1 d = 9//4
      2 print (d, type(d))
----> 3 print (x)

NameError: name 'x' is not defined

but types can be enforced, or used for data conversion

a = 1
b = float(a)
print (a, "::", b)
1 :: 1.0
s = "el valor de 'a' es "+str(a)
print (s)
el valor de 'a' es 1

Notebook cell outputs

a = 1
b = float(a)
a,b
(1, 1.0)
a = 1
a
b = float(a)
b
1.0
a = 1
print (a)
b = float(a)
b
1
1.0

Lists

ordered sequences of objects of any kind with cool indexing.

indexing starts at zero.

b = [1,10, 20.5, "hola", 10., 12, 13, 14., 15,16, 17., 18, 19, 20.]
print (len(b))
14
print (b[:3])
[1, 10, 20.5]
print (b[3:])
['hola', 10.0, 12, 13, 14.0, 15, 16, 17.0, 18, 19, 20.0]
print (b[-3:])
[18, 19, 20.0]
print (b[4])
10.0
print (b[5:10])
[12, 13, 14.0, 15, 16]
print (b[-5:-2])
[16, 17.0, 18]
print (b[::2])
[1, 20.5, 10.0, 13, 15, 17.0, 19]
print (b[::-1])
[20.0, 19, 18, 17.0, 16, 15, 14.0, 13, 12, 10.0, 'hola', 20.5, 10, 1]
b.append('elfin')
b
[1, 10, 20.5, 'hola', 10.0, 12, 13, 14.0, 15, 16, 17.0, 18, 19, 20.0, 'elfin']

can use variables as indexes

import numpy as np
i = np.random.randint(len(b))
print (i, '-->', b[i])
13 --> 20.0

truly any object

a = 32
b = 10
s = [1,2,3,"hola", [10, "nunca", 90], a==b, -32]
print (s)
[1, 2, 3, 'hola', [10, 'nunca', 90], False, -32]
print (len(s))
7
s[4]
[10, 'nunca', 90]
s[4][1]
'nunca'
s[3][1]
'o'
s[2][1]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-28-3e154303a25b> in <module>
----> 1 s[2][1]

TypeError: 'int' object is not subscriptable

some list operations

a = ["hola", 2, "adios"]
b = [-10., 1, [3, 4]]
a + b
['hola', 2, 'adios', -10.0, 1, [3, 4]]
a + a
['hola', 2, 'adios', 'hola', 2, 'adios']
a*2
['hola', 2, 'adios', 'hola', 2, 'adios']
a - b
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-09bd029d0285> in <module>
----> 1 a - b

TypeError: unsupported operand type(s) for -: 'list' and 'list'
2 in a
True
"hola" not in b
True
[3,4] in b
True

Strings

a string is like a special kind of list

a = "en un lugar de la mancha"
a
'en un lugar de la mancha'
a[3:]
'un lugar de la mancha'
a[-10:]
' la mancha'
a[::-1]
'ahcnam al ed ragul nu ne'
a[::2]
'e nlgrd amnh'
'lugar' in a
True

with special operations

words = a.split()
words
['en', 'un', 'lugar', 'de', 'la', 'mancha']
"::".join(words)
'en::un::lugar::de::la::mancha'
a.upper()
'EN UN LUGAR DE LA MANCHA'
a.startswith("en")
True
a.endswith("lugar")
False
a.find('lugar')
6
a[a.find('lugar'):]
'lugar de la mancha'

for loops

unlike other languages, for loops are defined over iterables. A list is an iterable, and there are many other iterables.

Python syntax is indented.

Observe python determines the semantics of * according to the context

b = [1,10, 20.5, "hola", 10.]
for i in b:
    print (i, "-->", type(i), "x2 -->", i*2)
1 --> <class 'int'> x2 --> 2
10 --> <class 'int'> x2 --> 20
20.5 --> <class 'float'> x2 --> 41.0
hola --> <class 'str'> x2 --> holahola
10.0 --> <class 'float'> x2 --> 20.0

another example of python as interpreted language

b = [1,10, 20.5, "hola", 10.]
for i in b:
    print (i, "-->", type(i), "x2 -->", i**2)
1 --> <class 'int'> x2 --> 1
10 --> <class 'int'> x2 --> 100
20.5 --> <class 'float'> x2 --> 420.25
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-55-4b8904782ded> in <module>
      1 b = [1,10, 20.5, "hola", 10.]
      2 for i in b:
----> 3     print (i, "-->", type(i), "x2 -->", i**2)

TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'int'

iterators

sometimes we do not need to hold all the contents of a list in memory, but they can be generated as they are being asked for.

k = range(-3,10,2)
k
range(-3, 10, 2)

size in memory

k.__sizeof__()
48
for i in k:
    print (i, end=", ")
-3, -1, 1, 3, 5, 7, 9, 
big_range = range(0,100000,2)
big_range.__sizeof__()
48
s = 0
for i in big_range:
    s += i
s
2499950000

if converted to a list, then they are physically in memory

a = list(big_range)
a.__sizeof__()
450088

zip iterators

a = ["nada", "adios", 10.]
b = [1,10, 20.5, "hola", 10.]

for i,j in zip(a,b):
    print (i,j)
nada 1
adios 10
10.0 20.5

Other control structures

string formatting / if / then / break / continue / while, etc.

b = [1,10, 20.5, "hola", 10., 12]
for i in b:
    if i=='hola':
        break
    print (i, type(i))
1 <class 'int'>
10 <class 'int'>
20.5 <class 'float'>
b = [1,10, 20.5, "hola", 10., 12]
for i in b:
    if i=='hola':
        break
    elif type(i)==int:
        print ("INT", end=" ")
    elif i>10:
        print (">10", end=" ")
    print (i, type(i))
INT 1 <class 'int'>
INT 10 <class 'int'>
>10 20.5 <class 'float'>
for i in b:
    if i=='hola':
        continue
    elif type(i)==int:
        print ("INT", end=" ")
    elif i>10:
        print (">10", end=" ")
    else:
        print ("UNK", end=" ")
    print (i, type(i))        
    
INT 1 <class 'int'>
INT 10 <class 'int'>
>10 20.5 <class 'float'>
UNK 10.0 <class 'float'>
INT 12 <class 'int'>
for pos, i in enumerate(b):
    if i=='hola':
        continue
    print ("%02d :: %5.1f :: %20s"%(pos,i,type(i)))
00 ::   1.0 ::        <class 'int'>
01 ::  10.0 ::        <class 'int'>
02 ::  20.5 ::      <class 'float'>
04 ::  10.0 ::      <class 'float'>
05 ::  12.0 ::        <class 'int'>
i=1
while i<len(b):
    print (i, b[i], type(b[i]))
    i += 1
1 10 <class 'int'>
2 20.5 <class 'float'>
3 hola <class 'str'>
4 10.0 <class 'float'>
5 12 <class 'int'>

Dictionaries

d = {"i1": 16, "nombre": "haskel", "edad": 32, 20: "el numero 20"}

d['i1']
16
d[20]
'el numero 20'
d.values()
dict_values([16, 'haskel', 32, 'el numero 20'])
d.keys()
dict_keys(['i1', 'nombre', 'edad', 20])
for i in d.keys():
    print("la clave", i, "tiene el valor", d[i])
la clave i1 tiene el valor 16
la clave nombre tiene el valor haskel
la clave edad tiene el valor 32
la clave 20 tiene el valor el numero 20
for k,v in d.items():
    print("la clave", k, "tiene el valor", v)    
la clave i1 tiene el valor 16
la clave nombre tiene el valor haskel
la clave edad tiene el valor 32
la clave 20 tiene el valor el numero 20

and can be updated

d[48] = "otro numero"
d["nada"] = 0
for k,v in d.items():
    print("la clave", k, "tiene el valor", v)    
la clave i1 tiene el valor 16
la clave nombre tiene el valor haskel
la clave edad tiene el valor 32
la clave 20 tiene el valor el numero 20
la clave 48 tiene el valor otro numero
la clave nada tiene el valor 0

Tuples

tuples are inmutable lists

a = (10,3,4,5)
a[3], a[::-1], sum(a)
(5, (5, 4, 3, 10), 22)
a[3]=1
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-4-36ab6b9a6038> in <module>
----> 1 a[3]=1

TypeError: 'tuple' object does not support item assignment

and thus can be used for keys, indexing, etc.

d = {}
d["hola"] = 3
d[1] = "one"
d[(4,5)] = "a tuple"
d
{'hola': 3, 1: 'one', (4, 5): 'a tuple'}

however

d[[4,5]]
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-9-857cb2d3ff14> in <module>
----> 1 d[[4,5]]

TypeError: unhashable type: 'list'