Python: the beginning

Versione di python

1
2
~$ python --version
Python 3.7.7

Jupyter Notebook

Scorciatoie

ctrl + ù (no tastierino alfanumerico) → commenta linea codice
ctrl + / (tastierino alfanumerico) → commenta linea codice

D D → elimina una cella
A → aggiungi una cella sopra quella attuale
B → aggiungi una cella sotto quella attuale
F → Find/Replace
Y → cambia cella in codice
M → cambia cella in Markdown

SHIFT + Enter → Esegui e passa alla cella successiva
CTRL + Enter → Esegui e passa alla cella successiva

Wrap Code

Celle a capo testo lungo in jupyter
Fonte

1
2
3
~$ conda activate py3
~$ jupyter --config-dir
/home/user/.jupyter

Creare la cartella ‘nbconfig’ nella config dir di jupyter

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mkdir /home/user/.jupyter/nbconfig
cd /home/user/.jupyter/nbconfig
cat > notebook.json
{
  "MarkdownCell": {
    "cm_config": {
      "lineWrapping": true
    }
  },
  "CodeCell": {
    "cm_config": {
      "lineWrapping": true
    }
  }
}
# Ctrl+D per chiudere il file

Altro

Pulire il workspace

1
%reset -f

R in Jupyter Notebook (Windows)

Ho provato con r-irkernel da conda, ma non mi piace perché scarica una propria versione di R, che può essere diversa rispetto la versione in locale. Quindi installo IRkernel da R che legge direttamente la versione di R in locale e usa le librerie preinstallate. Vado un po’ contro la filosofia degli environment di conda.

1
2
~$ conda activate py3
~$ "C:\Program Files\R\R-4.0.0\bin\x64\R.exe"
1
2
install.packages('IRkernel')
IRkernel::installspec()

Kernel list

1
~$ jupyter kernelspec list

Da ‘C:\Users\nomeUtente\AppData\Roaming\jupyter\kernels\ir\kernel.json’ posso modificare “display_name” aggiungendo la versione (nel comando installspec si può specificare il display_name) .

Conda Enviroments

Per creare un ambiente su cui lavorare, da terminale:

1
2
3
~$ conda info --envs
~$ conda create --name py3 python=3.7
Proceed ([y]/n)? y

Attivo l’environment e installo quello che serve

1
2
3
4
~$ conda activate py3
~$ conda install jupyter
~$ conda install pandas
~$ conda install numpy

Mi sposto dove voglio lavorare

1
2
3
~$ conda activate py3
~$ cd "/media/user/Public/Python/Course 001"
~$ juputer notebook

Per disattivare e/o rimuovere un environment

1
2
~$ conda deactivate
~$ conda remove --name py3 --all

Per esportare un environment

1
2
~$ conda activate py3
~$ conda env export > py3_env.yml

Basic Python

Utilizzo del r’nomeStringa’: qui il perché

1
2
3
# parametri, oggetti, variabili
num = 12
name = 'Sam'
1
2
3
# rimuovi oggetti
x = 1
del x
1
2
# stringa parametrica
'Numero {} e Nome {}'.format(num, name)
1
'Numero 12 e Nome Sam'
1
2
3
# stringa parametrica
print('Numero {} e Nome {}'.format(num, name))
print('Numero {one} e Nome {two}, e {one}'.format(one=num, two=name))
1
2
Numero 12 e Nome Sam
Numero 12 e Nome Sam, e 12
1
2
3
4
5
6
7
# posizioni stringa
s = 'abcde'
print(s[0]+s[4])
print(s[:2])
print(s[2:])
print(s[1:3])
print(s[::-1])	# inverti testo della stringa
1
2
3
4
5
ae
ab
cde
bc
edcba
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# lista
my_list = ['a', 'b', 'c']
print(my_list)

# lista estesa
my_list.append('d')
print(my_list)
print(my_list[1:3])

# modifica lista
my_list[0] = 'NEW'
print(my_list)

# rimuovo ultimo elemento dalla lista, se lo assegno quello rimosso viene assegnato al nuovo oggetto
# se definisci la posizione dentro il pop rimuove quello specifico elemento, altrimente prende l'ultimo di default
my_list_poppata = my_list.pop()
print(my_list)
print(my_list_poppata)

# lista nested
nest = [1, 2, [3, 4]]
print(nest[2])
print(nest[2][1])

# lista nested
nest = [1,2,3,[4,5,['target']]]
print(nest[3][2][0])
1
2
3
4
5
6
7
8
9
['a', 'b', 'c']
['a', 'b', 'c', 'd']
['b', 'c']
['NEW', 'b', 'c', 'd']
['NEW', 'b', 'c']
d
[3, 4]
4
target
1
2
3
4
5
# dizionario
d = {'key1':'item1','key2':'item2'}
# print(d[0]) # da errore
print(d)
print(d['key1'])
1
2
{'key1': 'item1', 'key2': 'item2'}
item1
1
2
3
4
# dizionario
d = {'k1':[1,2,3]}
my_list = d['k1'][1]
print(my_list)
1
2
1
2
3
4
# nested dizionari
d = {'k1':{'innerkey':[1,2,3]}}
print(d)
print(d['k1']['innerkey'][1])
1
2
{'k1': {'innerkey': [1, 2, 3]}}
2
1
2
3
4
# tupla
t = (1,2,3)
print(t[0])
# t[0] = 'NEW' # da errore perché una tupla è immutabile, diversamente dalle liste
1
1
1
2
3
4
5
6
7
8
9
# set (univoci)
print({1, 2, 3, 3})
print(set([1,1,1,1,2,3,3]))

s = {1,2,3}
s.add(5)
print(s)
s.add(5)
print(s)
1
2
3
4
{1, 2, 3}
{1, 2, 3}
{1, 2, 3, 5}
{1, 2, 3, 5}
1
2
3
# booleans, and, or
print((True) and (False))
print((True) or (False))
1
2
False
True
1
2
3
4
5
6
7
8
9
# if, ifelse
if 1==2:
    print('uno')
elif 1==3:
    print('due')
elif 1==5:
    print('tre')
else:
    print('quattro')
1
quattro
1
2
3
4
# for loops
seq = [1,2,3,4,5]
for item in seq:
    print(item)
1
2
3
4
5
1
2
3
4
5
1
2
3
4
5
# while loops
i = 1
while i < 5:
    print('i is: {}'.format(i))
    i = i+1
1
2
3
4
i is: 1
i is: 2
i is: 3
i is: 4
1
2
3
4
# range
print(range(5))
for i in range(5):
    print(i)
1
2
3
4
5
6
range(0, 5)
0
1
2
3
4
1
2
3
4
5
6
7
8
# list comprehension
x = [1,2,3,4]
out = []
for item in x:
    out.append(item**2)
print(out)

print([item**2 for item in x])
1
2
[1, 4, 9, 16]
[1, 4, 9, 16]
1
2
3
4
5
6
7
8
9
10
# functions
def my_func(parametro='default'):
    """
    documentazione che posso mostrare con shift+tab quando richiamo la funzione
    """
    print(parametro)

my_func()
my_func('o non default')
my_func('this is the question')
1
2
3
default
o non default
this is the question
1
my_func
1
<function __main__.my_func(parametro='default')>
1
2
3
4
def square(x):
    return x**2
out = square(2)
print(out)
1
4
1
2
3
4
5
6
7
8
9
10
11
# lambda functions
def times2(var):
    return var*2
print(times2(5))

def times2(var):return var*2
print(times2(5))

# lambda expression
t = lambda var: var*2
print(t(5))
1
2
3
10
10
10
1
2
3
4
5
6
7
8
# map
seq = [1,2,3,4,5]
print(map(times2, seq))
print(list(map(times2, seq)))

# lambda expression
print(list(map(t, seq)))
print(list(map(lambda num: num*2, seq)))
1
2
3
4
<map object at 0x0000020AAA401EC8>
[2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]
[2, 4, 6, 8, 10]
1
2
3
# filter
print(filter(lambda num: num%2 == 0, seq))
print(list(filter(lambda num: num%2 == 0, seq)))
1
2
<filter object at 0x0000020AAA4A1188>
[2, 4]
1
2
# methods
st = 'Ciao! Sono Nessuno'
1
2
3
4
5
6
# dopo il punto se usi tab suggerisce i metodi
print(st.lower())
print(st.upper())
print(st.split())
print(st.split('!'))
print(st.split('!')[1])
1
2
3
4
5
ciao! sono nessuno
CIAO! SONO NESSUNO
['Ciao!', 'Sono', 'Nessuno']
['Ciao', ' Sono Nessuno']
 Sono Nessuno
1
2
3
4
d = {'k1':1, 'k2':2}
print(d)
# con tab escono i methods
print(d.values())
1
2
{'k1': 1, 'k2': 2}
dict_values([1, 2])
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# cerco elemento in lista, in method
print('x' in [1,2,3])
print('x' in ['x','y','z'])

# con la tupla
x = [(1,2), (3,4), (5,6)]
print(x[0][0])

# for con tuple
for item in x:
    print(item)

for (a,b) in x:
    print(a)
    
for a,b in x:
    print(a)
    print(b)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
False
True
1
(1, 2)
(3, 4)
(5, 6)
1
3
5
1
2
3
4
5
6

Esercizi!

1
2
3
4
5
6
7
8
9
10
11
# trova cani
def findDog(st):
    return 'dog' in st.lower().split()

# conta cani
def countDog(st):
    count = 0
    for word in st.lower().split():
        if word == 'dog':
            count += 1
    return count
1
2
# trova gli elementi di un vettore che iniziano con la 'a'
print(list(filter(lambda parola: parola[0] == "a", vettore)))

Utili

L’imprecisione del float

Il problema dei linguaggi dinamici: non hai controllo sui type casting e si perdono dati senza sapere da dove. Evita il float se ti interessa la precisione (cit. Luca).
Segue un esempio problema:

1
int(((10**9-1)/9)**2)
1
12345678987654320
1
int(((10**9-1)/9))**2
1
12345678987654321

Il float di default in Python (3.7) perde dati oltre la 16esima cifra, quindi assegnando l’int a posteriori la perdita d’informazione già c’è stata. Invece, l’int prima del quadrato consente di lavorare sempre su int prima del raggiungimento della 16esima cifra.