py
py
Python
• Possiede una vasta gamma di librerie da cui attingere: NumPy, Pandas, TensorFlow,
Django, Flask, e molte altre.
Python è un linguaggio interpretato, il che significa che il codice viene eseguito riga per riga da
un interprete. Non è necessario compilare il codice prima di eseguirlo.
Quando scrivi ed esegui questo codice, Python lo interpreta e stampa il messaggio "Ciao,
mondo!" sulla console. Ovvero, che al contrario dei linguaggi compilati (che hanno bisogno di
essere compilati) il codice sorgente (il file .py in Python) non viene tradotto in un programma
binario (eseguibile) prima dell’esecuzione invece succede appunto che un interprete legge,
analizza e traduce il codice una riga alla volta mentre il programma è in esecuzione. Lo
svantaggio principale è che la velocità è nettamente inferiore rispetto ai linguaggi compilati,
perché il codice viene interpretato durante l’esecuzione.
39
40 CAPITOLO 6. PYTHON
6.3 Liste
Python fornisce molti diversi contenitori. Una lista è una collezione non ordinata del tipo:
1 >>> l = [1, 2, 3, 4, 5]
2 >>> type(l)
3 <type "list">
4
5 >>> l[2]
6 3
7
6.4 Stringhe
1 >>> a = "hello"
2 >>> a[0]
3 "h"
4
5 >>> a[1]
6 "e"
6.5. VARIABILI MUTABILI ED IMMUTABILI 41
8 >>> a[-1]
9 "o"
• Mutabili (list)
Da notare il fatto che la di↵erenza tra variabili mutabili e immutabili non riguarda la ca-
pacità di modificare la variabile stessa, ma piuttosto se è possibile modificare il valore interno
dell’oggetto a cui la variabile fa riferimento.
6.5.1 Immutabili
Gli int in Python sono immutabili: non puoi modificare direttamente un int esistente.
Ogni volta che "modifichi" un int , in realtà stai ne creando uno nuovo. Allora quello che ho
fatto è non modificare il numero intero originale bensì creare un nuovo int ed il riferimento
della variabile a viene aggiornato per puntare il nuovo numero. Lo stesso vale per str , float
e gli altri.
6.5.2 Mutabili
Le liste in Python sono mutabili: puoi cambiare il contenuto della lista senza creare una nuova
lista.
1 >>> thing =[49 ,52] #Ho una lista composta da due elementi -> 49 ,52
2 >>> thing. append ("cat") # Aggiungo infondo -> [49 , 52, "cat "]
3 >>> thing [1]="dog" # Sostituisco nella posizione [1] , "dog" -> [49 , "
dog", "cat "]
una referenza) ad essi o quando vengono passati ad una funzione. In Python infatti tutte le
variabili sono passate per referenza all’oggetto. Una volta che un oggetto non ha più nomi viene
cancellato dalla memoria automaticamente
6.7 Tuple
Simile a list ma non mutabile:
1 >>> t = 12345 , 54321 , " hello!"
2 >>> t[0]
3 12345
4
5 >>> t
6 (12345 , 54321 , "hello!")
7
8 >>> u = (0, 2)
6.8 Dictonary
Un dictionary è un’efficiente tabella chiave-valore (mutabile).
1 >>> tel = {"laure": 5752 , "paul": 5578}
2 >>> tel[" francis "] = 5915
3
4 >>> tel
5 {"paul": 5578 , " francis ": 5915 , "laure ": 5752}
6
7 >>> tel["paul"]
8 5578
9
• Metodo 1:
1 s = "" # Si inizia con una stringa vuota "s"
2 for data in container : # Questo pezzo significa che per ogni
elemento "data" nel contenitore " container " avviene la cosa
successiva
6.10. IF, THEN, ELSE 43
In questo caso invece abbiamo usato il metodo str.join() sempre per concatenare le strin-
ghe. Tale metodo prende una lista (o qualsiasi iterabile, contenitore) di stringhe come input
e combina tutti gli elementi della lista in un’unica stringa, aggiungendo eventualmente un
separatore (in questo caso, una stringa vuota " ").
Il primo approccio so↵re del fatto che, siccome le stringhe sono immutabili, ogni volta viene
allocato lo spazio per un nuovo oggetto il cui nome è s . Nel secondo esempio l’allocazione in
memoria avviene una volta sola per la stringa finale.
dove:
allora posso combinare il ciclo con il metodo appena visto ed ottengo per esempio:
44 CAPITOLO 6. PYTHON
così il ciclo for assegna ogni numero generato da range() alla variabile i e lo stampa: 0, 1,
2, 3. In quest caso start e step potevano essere omessi e si sarebbe ottenuto lo stesso risultato:
1 for i in range (4): #range (4) genera i numeri da 0 a 3
2 print (i)
Quella del segnaposto %s è una vecchia sintassi oggi sostituita per lo più da: .format() ,
ovvero:
1 for word in ("cool", " powerful ", " readable "):
2 print (" Python is {}" . format (word)) #il segna posto ora e’ "{}"
6.12 while/break/continue
Nel caso di while con break si ha:
1 z = 1+1j # Definisco il numero complesso z
2 while abs(z) < 100: # Continua finche ’ il modulo di z e’ minore di
100
3 if z.imag == 0: # Se la parte immaginaria e’ 0
4 break # Esce dal ciclo
5 z = z**2 + 1 # Aggiorna z elevandolo al quadrato e sommando 1
• La parte immaginaria è diversa da zero allora il ciclo non si interrompe e z viene aggiornato
2
z = z2 + 1 = 1 + 1j + 1 = 1 + 2 j
6.13 Funzioni
Funzione simile alla void in C++: (senza valore di ritorno)
1 def test (): # indica che stai definendo una funzione chiamata test
2 print ("in test function ")
3 test () # Quando scrivi test (), stai chiamando la funzione . Python
eseguira ’ il corpo della funzione , che in questo caso stampa il
messaggio .
In questo caso non c’è valore di ritorno (come in una funzione void in C++). Python utilizza
la parola chiave None per indicare un valore di ritorno "vuoto".
Funzione con valore di ritorno:
1 def area disco(r): # indica che stai definendo una funzione chiamata
area_disco che accetta un parametro r
2 return 3.14*r*r
3 area disco (1.5) # Quando scrivi area_disco (1.5) , stai chiamando la
funzione e passando il valore 1.5 come parametro
mi ritorna allora il valore: 7.064999999. Inoltre se assegni il risultato ad una variabile, puoi
usarlo successivamente:
1 def area disco(r):
2 return 3.14*r*r
3
Infatti i parametri “posizionali” devono precedere quelli “named”, significa che una volta
specificati parametri con nome non ne possono più essere passati come posizionali.
a priori, non sa quali sono i tipi degli argomenti ed eventuali inconsistenze producono errori
solo quando la funzione viene eseguita. In questo modo Python implementa naturalmente il
polimorfismo, cioè una stessa funzione può essere usata per dati di tipo diverso.
Facciamo un esempio:
1 def sum_of (* items):
2 result = items [0] # Prende il primo elemento della tupla items e
lo assegna a result
3 for item in items [1:]: # Itera sugli elementi di items a partire
dal secondo
4 result = result + item # Somma ogni elemento al risultato
5 print ( result )
in particolare:
• item_of(2, 3, 5) ) 10
• item_of[2, b] ) Error
in ogni caso si può forzare l’uso di variabili globali con la keyword global per esempio in
questo modo:
1 a = 2; b = 1 # globali
2
3 def f1(x):
4 return a*x + b
5
6 def f2(x):
7 global a
8 a=3
9 return a*x + b
48 CAPITOLO 6. PYTHON
10
6.20 Classi
Come in C++ consentono di creare oggetti che combinano dati (proprietà o attributi) e funzio-
nalità (metodi).
Una classe è una "struttura" che definisce come un oggetto dovrebbe comportarsi e quali dati
dovrebbe contenere. Mentre un oggetto è un’istanza della classe, ovvero una versione concreta
e specifica di quella struttura.
La forma più semplice di definizione di una classe è del tipo:
1 class NomeClasse :
2 <istruzione -1>
3 ...
4 <istruzione -N>
Tutti i metodi devono avere come primo argomento l’istanza stessa (che alla chiamata non
viene passata)
6.20.1 Esempio
1 class vector :
2 def __init__ (self ,x,y):
3 self.x = x
4 self.y = y
5 def __add__ (self ,b):
6 return vector (self.x + b.x, self.y + b.y)
7 def __str__ (self):
8 return "(" + str(self.x) + "," + str(self.y) + ")"
9 a = vector (2, 2)
10 b = vector (3, 3)
11 c = a + b
12 print (c)
6.21. MODULI 49
6.20.2 Ereditarietà
Anche in Python si può ereditare una classe derivata da una classe base. La sintassi è:
1 class ClasseDerivata ( ClasseBase ):
Per esempio:
1 class vector :
2 def __init__ (self ,x,y):
3 self.x = x
4 self.y = y
5 def __add__ (self ,b):
6 return vector (self.x + b.x, self.y + b.y)
7 def __str__ (self):
8 return str(self.x) + "," + str(self.y)
9
6.21 Moduli
I moduli sono le librerie di Python ed hanno il grosso vantaggio di essere portabili su vari SO
(no compilazione). In particolare file contenenti codice Python che possono includere funzioni,
classi, e variabili, o anche eseguire codice direttamente. I moduli permettono di organizzare e
riutilizzare il codice, semplificando lo sviluppo di programmi grandi e complessi.
Utilità:
Python ha una vasta gamma di moduli integrati come: sys , os , math . Si possono poi
installare anche moduli (librerie) da terze parti tramite pip come: numpy , pandas .
Vediamo degli esempi di importazione di un modulo:
Attenzione! Se definite una funzione con lo stesso nome di una presente nel modulo
“sovrascrivete” quella del modulo (perché viene usato senza utilizzarne il nome).
6.21.1 Sys
Il modulo sys fornisce funzionalità legate all’interprete Python. Chiamo il seguente file:
test.py
1 import sys
2 print (sys.argv) # Accede alla funzione "argv" del modulo "sys" e
stampa gli argomenti passati allo script
infatti per accedere alle funzioni di sys , è necessario usare il nome del modulo come prefisso.
allora in output:
> ./ test.py test arguments
[" file.py", "test", " arguments "]
6.21.2 Os
Il modulo os fornisce funzioni per interagire con il sistema operativo. Chiamo il seguente file:
test.py
1 import os
2 os. listdir (".") # Lista dei file nella directory corrente
3 print (files )
allora:
[ " inherit4 .jpg", " introduzione .aux", " introduzione .log", ...]
6.21.3 Numpy
Numpy è uno dei modulo più importanti, si tratta di un modulo per la gestione degli array
N-dimensionali (simile a list ma con calcolo vettoriale (e più efficiente)). Di fatto è un container
“mutabile” ed è una librearia fondamentale per il calcolo numerico.
1 import numpy as np;
2
Varie opzioni:
6.21. MODULI 51
Inoltre con il modulo Numpy abbiamo tante opzioni di inizializzazioni diverse, per esempio:
1 import numpy as np
2 x1 = np. linspace (0 ,100 ,100) # Crea 100 valori equispaziati tra 0 e
100
3 x2 = np.zeros (100 , float ) # Crea un array di 100 elementi
inizializzati a 0
4 x3 = np.ones (100 , float ) # Crea un array di 100 elementi
inizializzati a 1
5 x4 = np.ones (100 , float )*5 # Crea un array di 100 elementi
inizializzati a 5
Questo codice utilizza il modulo numpy per creare array con diverse modalità di inizializ-
zazione. Vediamo nel dettaglio cosa fanno queste righe e come funzionano.
dove:
Slicing Multidimensionale
Con NumPy, puoi fare slicing anche sugli array multidimensionali.
1 mat = np.array ([[1 , 2, 3],
2 [4, 5, 6],
3 [7, 8, 9]])
4
5 print (mat [:2 , :2]) # Prendi le prime due righe e le prime due colonne
l’output sarà:
1 [[1 2]
2 [4 5]]
Array Dinamici
NumPy non supporta nativamente array dinamici, perché gli array NumPy hanno una dimen-
sione fissa e ottimizzata per l’efficienza. Tuttavia, puoi utilizzare il metodo np.append per
aggiungere elementi a un array, creando un nuovo array che include gli elementi aggiunti.
Vediamo allora un esempio:
1 import numpy as np
2
7 print (a)
6.22. PYROOT 53
6.21.6 Scipy
Libreria scientifica di algoritmi e strumenti matematici da usare con numpy.
6.22 PyROOT
Si tratta della interfaccia a ROOT attraverso Python (è ancora un modulo in Python, una libreria
in C++).
vediamo un esempio:
1 import math
2 from ROOT import *
3
• import math ) Importa il modulo math di Python, che fornisce funzioni matematiche
come pi , sin , ecc.
• Run() ) Avvia l’applicazione, mantenendo aperta la finestra grafica finché l’utente non
la chiude.
allora il codice fa:
• Crea una funzione sin (x)/x definita nell’intervallo [ 5⇡, 5⇡].
• Disegna la funzione utilizzando ROOT.
• Mantiene aperta la finestra grafica finché l’utente non decide di chiuderla.
6.23 Matplotlib
So che matplotlib è una libreria per creare grafici e visualizzazioni di dati in Python. Vediamo
un esempio:
1 import matplotlib . pyplot as plt # Importa il modulo pyplot della
libreria " Matplotlib " con l’alias "plt"
2 import numpy as np
3
4 x = np. linspace ( -5* np.pi , 5* np.pi , 100) # Dopo questa riga , l’array
"x" contiene 100 numeri tra -5pi e 5pi
5 y = np.sin(x)/x # NumPy esegue l’operazione di calcolare la funzione
su tutto l’array "x", anche se in 0 la funzione e’ indefinita np
gestisce bene e pone y=1
6 plt.plot(x, y) # Disegna il grafico con i valori di x sull ’asse
orizzontale e y sull ’asse verticale
7 plt.show () # Mostra il grafico in una finestra o nel tuo ambiente di
sviluppo
dove x, y sono ascisse ed ordinate mentre [fmt] è la stringa per definire il formato della
linea e dei punti. Controlla colore, stile della linea e marker. Inoltre si può anche aggiungere
un altra variabile per argomenti opzionali per personalizzare il grafico (es. etichette, spessore
linea, titolo, ecc.). Per quanto riguarda [fmt] possiamo sostituirlo per esempio con i seguenti
parametri:
Caratteristica Simbolo
Colore "r" (rosso), "g" (verde), "b" (blu), "k" (nero)
Stile della linea "-" (continua), " " (tratteggiata), ":" (puntinata), "-." (trattini e punti)
Marker (punti) "o" (cerchio), "s" (quadrato), "⇤" (stella)
6.23. MATPLOTLIB 55
un esempio di applicativo è:
1 y1 = np.sin(x)
2 y2 = np.cos(x)
3
6.23.1 figure
Crea una nuova finestra o area di disegno per un grafico. Esempio:
1 import matplotlib . pyplot as plt
2
3 plt. figure ( figsize =(8 , 6)) # Crea una figura con dimensioni
specificate
4 plt.plot ([1 , 2, 3], [4, 5, 6])
5 plt.show ()
6.23.2 subplots
Crea più grafici (sottoplot) all’interno di una singola figura. Per esempio:
1 import matplotlib . pyplot as plt
2 import numpy as np
3
16 plt.show ()
6.23.3 legend
Visto prima in un esempio. Crea una legenda che spiega cosa rappresentano le linee o i punti in
un grafico.
7 plt.plot(x, y)
8 plt.title (" Grafico della funzione seno") # Titolo del grafico
9 plt. xlabel ("Asse X") # Etichetta asse X
10 plt. ylabel ("Asse Y") # Etichetta asse Y
11 plt.grid(True) # Mostra la griglia
12 plt.show ()
Un esempio di ottimizzazione riguarda i loop, per esempio diciamo che abbiamo il seguente
codice:
1 v = np.array ([0 1 2 3 4 5 6 7 8 9])
2 v2 = []
3 for i in range (10):
4 v2 = np. append (v2 ,v[i]*v[i])
considerando le dimensioni del loop non è un problema che sia lento ma rimane il fatto che
è velocizzabile, infatti come abbiamo detto, alla fine di ogni loop Python risalva in memoria il
dato occupando spazio, un primo modo è usare la comprehension list , per esempio:
1 v = np.array ([0 1 2 3 4 5 6 7 8 9])
2 v2 = [val*val for val in v]
la comprehension list passa tutto l’array ad una struttura C sottostante. E dunque è più
veloce, ma si può fare ancora di meglio con il generator
1 v = np.array ([0 1 2 3 4 5 6 7 8 9])
2 v2 = (val*val for val in v)
6.25. STAMPARE CON LE F-STRING 57
Il generator é simile ma non genera tutta la lista ma un valore alla volta (più efficiente).
Altri buoni consigli per velocizzare Python sono:
usare:
1 output = " ".join ([" Programming ", "is", "fun"])
invece di:
1 import math as m
2 a = m.sqrt (5)
22 )
23