Skip to content

3. Nozioni di base su Python

Image

3.1. Script [bases_01]: operazioni elementari

Lo script [bases_01] presenta le prime caratteristiche di Python.


# ----------------------------------
def affiche(chaine):
    # visualizza stringa
    print("chaine=%s" % chaine)


# ----------------------------------
def affiche_type(variable):
    # visualizza il tipo di variabile
    print("type[%s]=%s" % (variable, type(variable)))


# ----------------------------------
def f1(param):
    # aggiunge 10 a param
    return param + 10


# ----------------------------------
def f2():
    # restituisce una tupla di 3 valori
    return "un", 0, 100


# -------------------------------- programma principale ------------------------------------
# questo è un commento
# variabile utilizzata senza essere stata dichiarata
nom = "dupont"

# un output su schermo
print("nom=%s" % nom)

# un elenco con elementi di tipo diverso
liste = ["un", "deux", 3, 4]

# il numero dei suoi elementi
n = len(liste)

# un ciclo
for i in range(n):
    print("liste[%d]=%s" % (i, liste[i]))

# inizializzazione di 2 variabili con una tupla
(chaine1, chaine2) = ("chaine1", "chaine2")

# concatenazione delle 2 stringhe
chaine3 = chaine1 + chaine2

# visualizzazione del risultato
print("[%s,%s,%s]" % (chaine1, chaine2, chaine3))

# utilizzo di una funzione
affiche(chaine1)

# il tipo di una variabile può essere noto
affiche_type(n)
affiche_type(chaine1)
affiche_type(liste)

# il tipo di una variabile può cambiare durante l'esecuzione
n = "a changé"
affiche_type(n)

# una funzione può restituire un risultato
res1 = f1(4)
print("res1=%s" % res1)

# una funzione può restituire un elenco di valori
(res1, res2, res3) = f2()
print("(res1,res2,res3)=[%s,%s,%s]" % (res1, res2, res3))

# si sarebbero potuti recuperare questi valori in una variabile
liste = f2()
for i in range(len(liste)):
    print("liste[%s]=%s" % (i, liste[i]))

# test
for i in range(len(liste)):
    # visualizza solo le stringhe
    if type(liste[i]) == "str":
        print("liste[%s]=%s" % (i, liste[i]))

# altri test
for i in range(len(liste)):
    # visualizza solo i numeri interi >10
    if type(liste[i]) == "int" and liste[i] > 10:
        print("liste[%s]=%s" % (i, liste[i]))

# un ciclo while
liste = (8, 5, 0, -2, 3, 4)
i = 0
somme = 0
while i < len(liste) and liste[i] > 0:
    print("liste[%s]=%s" % (i, liste[i]))
    somme += liste[i]  # somma=somma+lista[i]
    i += 1  # i=i+1
print("somme=%s" % somme)
# fine programma

Commenti

  • riga 2: la parola chiave def definisce una funzione;
  • riga 2: la funzione riceve il parametro [chaine]. Non viene specificato il tipo del parametro. Python utilizza esclusivamente il passaggio per valore. Questo varia a seconda del dato:
    • per un tipo semplice (numero, booleano…), tale valore corrisponde al valore incapsulato dal dato (4, True…);
    • per un tipo complesso (lista, classe…), questo valore è l’indirizzo del dato;
  • righe 3-4: il contenuto della funzione. È indentato a destra di una tabulazione. È proprio questa indentazione, associata al carattere : dell’istruzione def, a definire il contenuto della funzione. Ciò vale per tutte le istruzioni che contengono un corpo: if, else, while, for, try, except;
  • riga 4: la sintassi utilizzata qui è [print('text1%F1text2%F2…' % data1, data2)]:
    • i [%Fi] (qui %s) sono formati di visualizzazione:
    • %s (string): per una stringa di caratteri;
    • %d (decimale): per i numeri interi decimali con segno;
    • %f (float): formato decimale per i numeri reali;
    • %e (esponenziale): formato esponenziale per un numero reale;
  • [data1, data2…] sono le espressioni di cui si desidera visualizzare il valore:
    • [data1] verrà visualizzato con il formato F1;
    • [data2] verrà visualizzata con il formato F2;
  • riga 10: Python gestisce internamente il tipo delle variabili. È possibile conoscere il tipo di una variabile con la funzione type(variable), che restituisce una variabile di tipo 'type'. L'espressione '%s' % (type(variable)) è una stringa di caratteri che rappresenta il tipo della variabile;
  • riga 25: il programma principale. Questo si trova solitamente (ma non necessariamente) dopo la definizione di tutte le funzioni dello script. Il suo contenuto non è indentato;
  • riga 28: in Python non si dichiarano le variabili. Python distingue tra maiuscole e minuscole. La variabile Nom è diversa dalla variabile nom. Una stringa di caratteri può essere racchiusa tra virgolette " o apostrofi '. È quindi possibile scrivere 'dupont' o "dupont";
  • riga 34: c'è una differenza tra una tupla (1,2,3) (notare le parentesi) e una lista [1,2,3] (notare le parentesi quadre). La tupla è immutabile, mentre la lista è modificabile. In entrambi i casi, l’elemento n. i è indicato come [i];
  • riga 40: range(n) è la tupla (0,1,2,…,n-1);
  • riga 41: il formato %d viene utilizzato per i numeri interi con segno;
  • riga 74: len(var) è il numero di elementi della collezione var (tupla, lista, dizionario…);
  • riga 84: la struttura [for in …] consente di iterare su una struttura iterabile. Le liste e le tuple sono elementi iterabili;
  • riga 86: gli altri operatori booleani sono or e not;
  • riga 93: calcola la somma dei numeri >0 presenti nella lista;

I risultati visualizzati sullo schermo sono i seguenti:


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_01.py
nom=dupont
liste[0]=un
liste[1]=deux
liste[2]=3
liste[3]=4
[chaine1,chaine2,chaine1chaine2]
chaine=chaine1
type[4]=<class 'int'>
type[chaine1]=<class 'str'>
type[['un', 'deux', 3, 4]]=<class 'list'>
type[a changé]=<class 'str'>
res1=14
(res1,res2,res3)=[un,0,100]
liste[0]=un
liste[1]=0
liste[2]=100
liste[0]=8
liste[1]=5
somme=13

Process finished with exit code 0

3.2. Script [bases_02]: stringhe di formattazione

Python 3 ha introdotto un nuovo modo di formattare le stringhe:


# stringhe di formattazione
# i formati sono quelli del linguaggio C
# intero
int1 = 10
print(f"[int1={int1}]")
print(f"[int1={int1:4d}]")
print(f"[int1={int1:04d}]")
# numero in virgola mobile
float1=8.2
print(f"[float1={float1}]")
print(f"[float1={float1:8.2f}]")
print(f"[float1={float1:.3e}]")
# stringa
str1="abcd"
print(f"[str1={str1}]")
print(f"[str1={str1:8s}]")
str2="jean de florette"
print(f"[{str2:20.10s}]")
# le stringhe formattate possono essere assegnate a variabili
str3=f"[{str2:20.10s}]"
print(str3)

La sintassi della stringa formattata è la seguente:

f'…{expr1:format1} …. {expr2:format2} ….'

dove:

  • [expri]: un'espressione;
  • [formati]: il formato dell'espressione [expri]. Questi formati sono quelli del linguaggio C:
    • %d: per i numeri interi;
    • %f: notazione decimale per i numeri reali;
    • %e: notazione esponenziale per i numeri reali;
    • %s: per le stringhe di caratteri. È il formato utilizzato quando non viene specificato alcun formato per [expri];
    • %nd, %nf, %ns: visualizza [expri] su n caratteri: la stringa viene troncata o completata con spazi;
  • riga 7: [04d], numero intero di 4 caratteri completato a sinistra con zeri;
  • riga 11: [8.2f], numero reale decimale di 8 caratteri, di cui 2 dopo la virgola;
  • riga 12: [.3e], numero reale in forma esponenziale con 3 cifre decimali per la mantissa;
  • riga 18: [20.10s], i primi 10 caratteri di una stringa riempita con spazi fino a raggiungere i 20 caratteri;

I risultati dell'esecuzione sono i seguenti:

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_02.py
[int1=10]
[int1=  10]
[int1=0010]
[float1=8.2]
[float1=    8.20]
[float1=8.200e+00]
[str1=abcd]
[str1=abcd    ]
[jean de fl          ]
[jean de fl          ]

Process finished with exit code 0

3.3. Script [bases_03]: conversioni di tipo

Qui ci interessano le conversioni di tipo con dati di tipo str (stringa di caratteri), int (intero), float (reale), bool (booleano).


# cambiamenti di tipo
# int --> str, float, bool
x = 4
print(x, type(x))
x = str(4)
print(x, type(x))
x = float(4)
print(x, type(x))
x = bool(4)
print(x, type(x))

# bool --> int, float, str
x = True
print(x, type(x))
x = int(True)
print(x, type(x))
x = float(True)
print(x, type(x))
x = str(True)
print(x, type(x))

# str --> int, float, bool
x = "4"
print(x, type(x))
x = int("4")
print(x, type(x))
x = float("4")
print(x, type(x))
x = bool("4")
print(x, type(x))

# float → str, int, bool
x = 4.32
print(x, type(x))
x = str(4.32)
print(x, type(x))
x = int(4.32)
print(x, type(x))
x = bool(4.32)
print(x, type(x))

# gestione degli errori di conversione di tipo
try:
    x = int("abc")
    print(x, type(x))
except ValueError as erreur:
    print(erreur)

# casi vari
x = bool("abc")
print(x, type(x))
x = bool("")
print(x, type(x))
x = bool(0)
print(x, type(x))
x = None
print(x, type(x))
x = bool(None)
print(x, type(x))
x = bool(0.0)
print(x, type(x))

# tutti i dati sono istanze di classe e, in quanto tali, dispongono di metodi
# stringa di caratteri
str1 = "abc"
print(str1.capitalize())
# numero intero
int1 = 4
print(int1.bit_length())
# booleano
bool1=True
print(bool1.conjugate())
# numero reale
float1=8.2
print (float1.is_integer())

Sono possibili numerose conversioni di tipo. Alcune potrebbero fallire, come quella alle righe 46-47 che tenta di trasformare la stringa 'abc' in un numero intero. Abbiamo gestito l'errore con una struttura try / except. Una forma generale di questa struttura

è la seguente:


try:
    actions
except Exception as ex:
    actions
finally:
    actions

Se una delle azioni del blocco try genera un'eccezione (segnala un errore), si passa immediatamente alla clausola except. Se le azioni del blocco try non generano un'eccezione, la clausola except viene ignorata. Gli attributi Exception e ex dell'istruzione except sono facoltativi. Quando sono presenti, Exception specifica il tipo di eccezione intercettata dall’istruzione except, mentre ex contiene l’eccezione che si è verificata. Possono esserci più istruzioni except, se si desidera gestire diversi tipi di eccezioni all’interno dello stesso try.

L'istruzione finally è facoltativa. Se presente, le azioni del finally vengono sempre eseguite, indipendentemente dal fatto che si sia verificata o meno un'eccezione.

Torneremo sulle eccezioni più avanti.

Le righe 49-61 mostrano vari tentativi di convertire un dato di tipo str, int, float, NoneType in un valore booleano. Ciò è sempre possibile. Le regole sono le seguenti:

  • bool(int i) è pari a False se i è pari a 0, True in tutti gli altri casi;
  • bool(float f) è pari a False se f è pari a 0,0, True in tutti gli altri casi;
  • bool(str stringa) è pari a False se stringa contiene 0 caratteri, True in tutti gli altri casi;
  • bool(None) restituisce False. None è un valore speciale che indica che la variabile esiste ma non ha alcun valore.

I risultati visualizzati sullo schermo sono i seguenti:

C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_03.py
4 <class 'int'>
4 <class 'str'>
4.0 <class 'float'>
True <class 'bool'>
True <class 'bool'>
1 <class 'int'>
1.0 <class 'float'>
True <class 'str'>
4 <class 'str'>
4 <class 'int'>
4.0 <class 'float'>
True <class 'bool'>
4.32 <class 'float'>
4.32 <class 'str'>
4 <class 'int'>
True <class 'bool'>
invalid literal for int() with base 10: 'abc'
True <class 'bool'>
False <class 'bool'>
False <class 'bool'>
None <class 'NoneType'>
False <class 'bool'>
False <class 'bool'>
Abc
3
1
False

Process finished with exit code 0

Si noti che tutti i dati sono oggetti, ovvero istanze di classe. Ciò significa che possono avere dei metodi. È quanto mostrano le righe 63-75 del codice. In questa sede non intendiamo spiegare cosa facciano i metodi utilizzati, ma semplicemente mostrare che esistono.

3.4. Script [bases_04]: ambito delle variabili

Lo script [bases_04] dimostra che Python non prevede il concetto di variabile con ambito a blocco:


# ambito delle variabili
i = 4
if True:
    i += 1
    j = 7
print(f"i={i}, j={j}")

Risultati

1
2
3
4
C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_04.py
i=5, j=7

Process finished with exit code 0

Commenti

I risultati evidenziano due aspetti:

  • riga 4: la variabile [i] del blocco [if] è la stessa della variabile i utilizzata alla riga 2;
  • riga 6: la variabile [j] è quella inizializzata nel blocco [if];

In alcuni linguaggi, in cui le variabili vengono dichiarate, una variabile definita in un blocco (come quello delle righe 3-5) non è nota al di fuori di esso. In Python, invece, non è così.

3.5. Script [bases_05]: liste - 1

Lo script [bases_05] è il seguente:


# liste unidimensionali
# inizializzazione
list1 = [0, 1, 2, 3, 4, 5]

# iterazione - 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
    print(f"list1[{i}]={list1[i]}")

list1[1] = 10
# iterazione - 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
    print(element)

# aggiunta di due elementi
list1[len(list1):] = [10, 11]
# il formato %s consente di visualizzare l'elenco su una sola riga
print("%s" % list1)

# eliminazione degli ultimi due elementi
list1[len(list1) - 2:] = []
# il formato predefinito consente di visualizzare l'elenco su una sola riga
print(f"{list1}")

# aggiunta di un elenco all’inizio dell’elenco
list1[:0] = [-10, -11, -12]
print(f"{list1}")

# inserimento di due elementi a metà dell'elenco
list1[3:3] = [100, 101]
print(f"{list1}")

# eliminazione di due elementi a metà dell'elenco
list1[3:4] = []
print(f"{list1}")

Note:

  • la notazione tabella[i:j] indica gli elementi da i a j-1 della tabella;
  • la notazione [i:] indica gli elementi a partire da i della tabella;
  • la notazione [:i] indica gli elementi da 0 a i-1 dell'array;
  • riga 19: print (%s) % (list1) visualizza la stringa: "[ list1[0], list1[2]…, list1[n-1]]";
  • riga 24: la sintassi print ('f{list1}') produce lo stesso risultato;

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_05.py
list1 a 6 éléments
list1[0]=0
list1[1]=1
list1[2]=2
list1[3]=3
list1[4]=4
list1[5]=5
list1 a 6 éléments
0
10
2
3
4
5
[0, 10, 2, 3, 4, 5, 10, 11]
[0, 10, 2, 3, 4, 5]
[-10, -11, -12, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 100, 101, 0, 10, 2, 3, 4, 5]
[-10, -11, -12, 101, 0, 10, 2, 3, 4, 5]

Process finished with exit code 0

3.6. Script [bases_06]: liste - 2

Il codice precedente può essere scritto in modo diverso (bases_06) utilizzando alcuni metodi delle liste:


# elenchi unidimensionali

# inizializzazione
list1 = [0, 1, 2, 3, 4, 5]

# scorrimento - 1
print(f"list1 a {len(list1)} éléments")
for i in range(len(list1)):
    print(f"list1[{i}]={list1[i]}")

# modifica di un elemento
list1[1] = 10

# scorrimento - 2
print(f"list1 a {len(list1)} éléments")
for element in list1:
    print(element)

# aggiunta di due elementi
list1.extend([10, 11])
print(f"{list1}")

# eliminazione degli ultimi due elementi
del list1[len(list1) - 2:]
print(f"{list1}")

# aggiunta di una tupla all'inizio dell'elenco
for i in (-12, -11, -10):
    list1.insert(0, i)
print(f"{list1}")

# inserimento a metà lista
for i in (101, 100):
    list1.insert(3, i)
print(f"{list1}")

# eliminazione a metà della lista
del list1[3:4]
print(f"{list1}")

I risultati ottenuti sono gli stessi della versione precedente.

3.7. script [bases_07]: il dizionario

Lo script [bases_07] mostra come definire e utilizzare un dizionario, talvolta chiamato tabella associativa.


# una funzione che verifica se la chiave «mari» esiste nel dizionario «conjoints»
def existe(conjoints, mari):
    if mari in conjoints:
        print(f"La clé [{mari}] existe associée à la valeur [{conjoints[mari]}]")
    else:
        print(f"La clé [{mari}] n'existe pas")


# ----------------------------- Main
# un dizionario
conjoints = {"Pierre": "Gisèle", "Paul": "Virginie", "Jacques": "Lucette", "Jean": ""}

# scorrimento - 1
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
for (clé, valeur) in conjoints.items():
    print(f"conjoints[{clé}]={valeur}")

# elenco delle chiavi del dizionario
print("liste des clés-------------")
clés = conjoints.keys()
print(f"{clés}")

# elenco dei valori del dizionario
print("liste des valeurs------------")
valeurs = conjoints.values()
print(f"{valeurs}")

# ricerca di una chiave
existe(conjoints, "Jacques")
existe(conjoints, "Lucette")
existe(conjoints, "Jean")

# eliminazione di una coppia chiave-valore
del (conjoints["Jean"])
print(f"Nombre d'éléments du dictionnaire : {len(conjoints)}")
print(f"{conjoints}")

# le chiavi e i valori di un dizionario non sono elenchi
print(f"type des clés : {type(clés)}")
print(f"type des valeurs : {type(valeurs)}")

# è possibile trasformarli in liste
lclés = list(clés)
print(f"clés : {type(lclés)}, {lclés}")
lvaleurs = list(valeurs)
print(f"valeurs : {type(lvaleurs)}, {lvaleurs}")

Note:

  • riga 11: definizione fissa di un dizionario;
  • riga 15: conjoints.items() rende congiunte le coppie (chiave, valore) del dizionario;
  • riga 20: conjoints.keys() restituisce le chiavi del dizionario come insieme;
  • riga 25: conjoints.values() restituisce i valori del dizionario «conjoints»;
  • riga 3: «mari» in «conjoints» restituisce True se la chiave mari esiste nel dizionario conjoints, altrimenti False;
  • riga 36: un dizionario può essere visualizzato su una sola riga.

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_07.py
Nombre d'éléments du dictionnaire : 4
conjoints[Pierre]=Gisèle
conjoints[Paul]=Virginie
conjoints[Jacques]=Lucette
conjoints[Jean]=
liste des clés-------------
dict_keys(['Pierre', 'Paul', 'Jacques', 'Jean'])
liste des valeurs------------
dict_values(['Gisèle', 'Virginie', 'Lucette', ''])
La clé [Jacques] existe associée à la valeur [Lucette]
La clé [Lucette] n'existe pas
La clé [Jean] existe associée à la valeur []
Nombre d'éléments du dictionnaire : 3
{'Pierre': 'Gisèle', 'Paul': 'Virginie', 'Jacques': 'Lucette'}
type des clés : <class 'dict_keys'>
type des valeurs : <class 'dict_values'>
clés : <class 'list'>, ['Pierre', 'Paul', 'Jacques']
valeurs : <class 'list'>, ['Gisèle', 'Virginie', 'Lucette']

Process finished with exit code 0

Note:

  • si noti alle righe 16-17 dei risultati che le chiavi e i valori di un dizionario non formano una lista, bensì un tipo 'dict_keys';
  • righe 18-19: una semplice modifica del tipo consente di convertirli in un tipo [list];

3.8. script [bases_08]: le tuple

La tupla presenta alcune somiglianze con la lista, ma non è modificabile:


# tupla
# inizializzazione
tuple1 = (0, 1, 2, 3, 4, 5)

# iterazione - 1
print(f"tuple1 a {len(tuple1)} elements")
for i in range(len(tuple1)):
    print(f"tuple1[{i}]={tuple1[i]}")

# iterazione - 2
print(f"tuple1 a {len(tuple1)} elements")
for element in tuple1:
    print(element)

# una tupla può essere visualizzata su una riga
print(f"tuple1={tuple1}")

# una tupla non può essere modificata
tuple1[0] = 10

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py
tuple1 a 6 elements
tuple1[0]=0
tuple1[1]=1
tuple1[2]=2
tuple1[3]=3
tuple1[4]=4
tuple1[5]=5
tuple1 a 6 elements
0
1
2
3
4
5
tuple1=(0, 1, 2, 3, 4, 5)
Traceback (most recent call last):
  File "C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_08.py", line 19, in <module>
    tuple1[0] = 10
TypeError: 'tuple' object does not support item assignment

Process finished with exit code 1

Note:

  • righe 17-20 dei risultati: dimostrano che una tupla non può essere modificata.

3.9. Script [bases_09]: elenchi e dizionari multidimensionali

Lo script [bases_09] mostra come definire e utilizzare una lista o un dizionario multidimensionale:


# liste multidimensionali
# inizializzazione
multi = [[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]

# iterazione
for i1 in range(len(multi)):
    for i2 in range(len(multi[i1])):
        print(f"multi[{i1}][{i2}]={multi[i1][i2]}")

# visualizzazione su una riga
print(f"multi={multi}")

# dizionari multidimensionali
# inizializzazione
multi = {"zéro": [0, 1], "un": [10, 11, 12, 13], "deux": [20, 21, 22, 23, 24]}

# scorrimento
for (clé, valeur) in multi.items():
    for i2 in range(len(valeur)):
        print(f"multi[{clé}][{i2}]={multi[clé][i2]}")

# visualizzazione su una riga
print(f"multi={multi}")

Commenti

  • riga 7: multi[i1] è una lista;
  • riga 18: «valeur» è un elenco;

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_09.py
multi[0][0]=0
multi[0][1]=1
multi[0][2]=2
multi[1][0]=10
multi[1][1]=11
multi[1][2]=12
multi[1][3]=13
multi[2][0]=20
multi[2][1]=21
multi[2][2]=22
multi[2][3]=23
multi[2][4]=24
multi=[[0, 1, 2], [10, 11, 12, 13], [20, 21, 22, 23, 24]]
multi[zéro][0]=0
multi[zéro][1]=1
multi[un][0]=10
multi[un][1]=11
multi[un][2]=12
multi[un][3]=13
multi[deux][0]=20
multi[deux][1]=21
multi[deux][2]=22
multi[deux][3]=23
multi[deux][4]=24
multi={'zéro': [0, 1], 'un': [10, 11, 12, 13], 'deux': [20, 21, 22, 23, 24]}

Process finished with exit code 0

3.10. Script [bases_10]: collegamenti tra stringhe e liste

Lo script [bases_10] mostra come recuperare in un elenco gli elementi di una stringa separati da un unico separatore.


# da stringa a elenco
chaine = '1:2:3:4'
liste = chaine.split(':')
print(type(liste))

# visualizzazione elenco
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")

# da elenco a stringa
chaine2 = ":".join(liste)
print(f"chaine2={chaine2}")

# aggiungiamo un campo vuoto
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")

# visualizzazione a lista
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")

# aggiungiamo di nuovo un campo vuoto
chaine += ":"
print(f"chaine={chaine}")
liste = chaine.split(":")

# visualizzazione elenco
print(f"liste a {len(liste)} éléments")
print(f"liste={liste}")

Note:

  • riga 3: il metodo chaine.split(separatore) suddivide la stringa di caratteri chaine in elementi separati da séparateur e li restituisce sotto forma di lista. Pertanto, l’espressione '1:2:3:4'.split(":") ha come valore la lista ('1','2','3','4');
  • riga 11: 'separatore'.join(lista) ha come valore la stringa 'lista[0]+separatore+lista[1]+separatore+…'.

Risultati


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_10.py
<class 'list'>
liste a 4 éléments
liste=['1', '2', '3', '4']
chaine2=1:2:3:4
chaine=1:2:3:4:
liste a 5 éléments
liste=['1', '2', '3', '4', '']
chaine=1:2:3:4::
liste a 6 éléments
liste=['1', '2', '3', '4', '', '']

Process finished with exit code 0

3.11. Script [bases_11]: le espressioni regolari

Lo script [bases_11] mostra come utilizzare le espressioni regolari:


# importiamo il modulo delle espressioni regolari
import re


# --------------------------------------------------------------------------
def compare(modèle, chaine):
    # confronta la stringa [chaîne] con il modello [modèle]
    # visualizzazione dei risultati
    print(f"\nRésultats({chaine},{modèle})")
    match = re.match(modèle, chaine)
    if match:
        print(match.groups())
    else:
        print(f"La chaîne [{chaine}] ne correspond pas au modèle [{modèle}]")


# espressioni regolari in Python
# recupera i diversi campi di una stringa
# il modello: una sequenza di cifre circondata da caratteri qualsiasi
# si desidera estrarre solo la sequenza di cifre
modèle = r"^.*?(\d+).*?$"

# si confronta la stringa con il modello
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")

# il modello: una sequenza di cifre circondata da caratteri qualsiasi
# si desidera la sequenza di cifre insieme ai campi che la precedono e la seguono
modèle = r"^(.*?)(\d+)(.*?)$"

# si confronta la stringa con il modello
compare(modèle, "xyz1234abcd")
compare(modèle, "12 34")
compare(modèle, "abcd")

# il modello: una data nel formato gg/mm/aa
modèle = r"^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$"
compare(modèle, "10/05/97")
compare(modèle, " 04/04/01 ")
compare(modèle, "5/1/01")

# il modello: un numero decimale
modèle = r"^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$"
compare(modèle, "187.8")
compare(modèle, "-0.6")
compare(modèle, "4")
compare(modèle, ".6")
compare(modèle, "4.")
compare(modèle, " + 4")
# fine

Note:

  • si noti il modulo [re] importato alla riga 2. È proprio questo modulo a contenere le funzioni per la gestione delle espressioni regolari;
  • riga 10: il confronto tra una stringa e un'espressione regolare (modello) restituisce il valore booleano True se la stringa corrisponde al modello, False in caso contrario;
  • riga 12: match.groups() è una tupla i cui elementi sono le parti della stringa che corrispondono agli elementi dell’espressione regolare racchiusi tra parentesi. Nel modello:
    • ^.*?(\d+).*?, match.groups() sarà una tupla a un elemento perché c’è una parentesi;
    • ^(.*?)(\d+)(.*?)$, match.groups() sarà una tupla di 3 elementi perché ci sono tre parentesi;
  • riga 21: un'espressione regolare letterale è indicata con r"xxx". È il simbolo r che trasforma la stringa in un'espressione regolare;

Le espressioni regolari ci consentono di verificare il formato di una stringa di caratteri. In questo modo è possibile verificare che una stringa che rappresenta una data sia nel formato gg/mm/aa. A tal fine si utilizza un modello e si confronta la stringa con tale modello. Pertanto, in questo esempio, g, m e a devono essere cifre. Il modello di un formato di data valido è quindi "\d\d/\d\d/\d\d", dove il simbolo \d indica una cifra. I simboli utilizzabili in un modello sono i seguenti:

Carattere
Descrizione
\
Indica il carattere successivo come carattere speciale o letterale. Ad esempio, "n" corrisponde al carattere "n", mentre "\n" corrisponde a un carattere di nuova riga. La sequenza "\\" corrisponde a "\", mentre "\(" corrisponde a "(".
^
Corrisponde all'inizio della stringa.
$
Corrisponde alla fine della stringa.
*
Corrisponde al carattere precedente, zero o più volte. Pertanto, "zo*" corrisponde a "z" o a "zoo".
+
Corrisponde al carattere precedente, una o più volte. Pertanto, "zo+" corrisponde a "zoo", ma non a "z".
?
Corrisponde al carattere precedente, zero o una volta. Ad esempio, "a?ve?" corrisponde a "ve" in "lever".
.
Corrisponde a qualsiasi singolo carattere, eccetto il carattere di nuova riga.
(modello)
Cerca modèle e memorizza la corrispondenza. La sottostringa corrispondente può essere estratta dalla raccolta match.groups(). Per trovare corrispondenze con caratteri tra parentesi ( ), utilizzare "\(" o "\)".
x|y
Corrisponde sia a x sia a y. Ad esempio, "z|foot" corrisponde a "z" o a "foot". "(z|f)oo" corrisponde a "zoo" o a "foo".
{n}
n è un numero intero non negativo. Corrisponde esattamente a n volte il carattere. Ad esempio, "o{2}" non corrisponde a "o" in "Bob," ma alle prime due "o" in "fooooot".
{n,}
n è un numero intero non negativo. Corrisponde ad almeno n volte il carattere. Ad esempio, "o{2,}" non corrisponde alla "o" in "Bob", ma a tutte le "o" in "fooooot". "o{1,}" equivale a "o+" e "o{0,}" equivale a "o*".
{n,m}
m e n sono numeri interi non negativi. Corrisponde ad almeno n e al massimo m volte il carattere. Ad esempio, "o{1,3}" corrisponde alle prime tre "o" in "foooooot" e "o{0,1}" equivale a "o?".
[xyz]
Insieme di caratteri. Corrisponde a uno dei caratteri indicati. Ad esempio, "[abc]" corrisponde alla "a" in "plat".
[^xyz]
Set di caratteri negativo. Corrisponde a qualsiasi carattere non indicato. Ad esempio, "[^abc]" corrisponde alla "p" in "plat".
[a-z]
Intervallo di caratteri. Corrisponde a qualsiasi carattere compreso nella serie specificata. Ad esempio, "[a-z]" corrisponde a qualsiasi carattere alfabetico minuscolo compreso tra "a" e "z".
[^m-z]
Intervallo di caratteri negativo. Corrisponde a qualsiasi carattere non presente nella serie specificata. Ad esempio, "[^m-z]" corrisponde a qualsiasi carattere non compreso tra "m" e "z".
\b
Corrisponde a un delimitatore che rappresenta una parola, ovvero alla posizione tra una parola e uno spazio. Ad esempio, "er\b" corrisponde a "er" in "lever", ma non a "er" in "verbe".
\B
Corrisponde a un delimitatore che non rappresenta una parola. "en*t\B" corrisponde a "ent" in "bien entendu".
\d
Corrisponde a un carattere che rappresenta una cifra. Equivale a [0-9].
\D
Corrisponde a un carattere che non rappresenta una cifra. Equivale a [^0-9].
\f
Corrisponde a un carattere di fine pagina.
\n
Corrisponde a un carattere di nuova riga.
\r
Corrisponde a un carattere di ritorno a capo.
\s
Corrisponde a qualsiasi carattere di spaziatura, inclusi spazio, tabulazione, salto di pagina, ecc. Equivale a "[ \f\n\r\t\v]".
\S
Corrisponde a qualsiasi carattere non bianco. Equivale a "[^ \f\n\r\t\v]".
\t
Corrisponde a un carattere di tabulazione.
\v
Corrisponde a un carattere di tabulazione verticale.
\w
Corrisponde a qualsiasi carattere che rappresenti una parola e che includa un trattino basso. Equivale a "[A-Za-z0-9_]".
\W
Corrisponde a qualsiasi carattere che non rappresenti una parola. Equivale a "[^A-Za-z0-9_]".
\num
Corrisponde a num, dove num è un numero intero positivo. Fa riferimento alle corrispondenze memorizzate. Ad esempio, "(.)\1" corrisponde a due caratteri identici consecutivi.
\n
Corrisponde a n, dove n è un valore di escape ottale. I valori di escape ottali devono comprendere 1, 2 o 3 cifre. Ad esempio, sia "\11" che "\011" corrispondono a un carattere di tabulazione. "\0011" equivale a "\001" e "1". I valori di escape ottali non devono superare 256. In caso contrario, nell'espressione verrebbero prese in considerazione solo le prime due cifre. Consente di utilizzare i codici ASCII nelle espressioni regolari.
\xn
Corrisponde a n, dove n è un valore di escape esadecimale. I valori di escape esadecimali devono obbligatoriamente comprendere due cifre. Ad esempio, "\x41" corrisponde a "A". "\x041" equivale a "\x04" e "1". Consente di utilizzare i codici ASCII nelle espressioni regolari.

Un elemento in un modello può essere presente una o più volte. Consideriamo alcuni esempi relativi al simbolo \d, che rappresenta una cifra:

modello
significato
\d
una cifra
\d?
0 o 1 cifra
\d*
0 o più cifre
\d+
1 o più cifre
\d{2}
2 cifre
\d{3,}
almeno 3 cifre
\d{5,7}
da 5 a 7 cifre

Immaginiamo ora il modello in grado di descrivere il formato previsto per una stringa di caratteri:

stringa ricercata
modello
una data nel formato gg/mm/aa
\d{2}/\d{2}/\d{2}
un'ora nel formato hh:mm:ss
\d{2}:\d{2}:\d{2}
un numero intero senza segno
\d+
una sequenza di spazi, eventualmente vuota
\s*
un numero intero senza segno che può essere preceduto o seguito da spazi
\s*\d+\s*
un numero intero che può essere con segno e preceduto o seguito da spazi
\s*[+|-]?\s*\d+\s*
un numero reale senza segno che può essere preceduto o seguito da spazi
\s*\d+(.\d*)?\s*
un numero reale che può essere con segno e preceduto o seguito da spazi
\s*[+-]?\s*\d+(.\d*)?\s*
una stringa contenente la parola "giusto"
\bjusto\b

È possibile specificare dove cercare il modello nella stringa:

modello
significato
^modello
il modello inizia la stringa
modello$
il modello conclude la stringa
^modello$
il modello inizia e termina la stringa
modello
il modello viene cercato in tutta la stringa a partire dall'inizio della stessa.
stringa cercata
modello
una stringa che termina con un punto esclamativo
!$
una stringa che termina con un punto
\.$
una stringa che inizia con la sequenza //
^//
una stringa composta da una sola parola, eventualmente preceduta o seguita da spazi
^\s*\w+\s*$
una stringa contenente due parole, eventualmente precedute o seguite da spazi
^\s*\w+\s*\w+\s*$
una stringa contenente la parola "secret"
\bsecret\b

I sottoinsiemi di un modello possono essere "recuperati". In questo modo, non solo è possibile verificare che una stringa corrisponda a un modello specifico, ma è anche possibile recuperare all’interno di tale stringa gli elementi corrispondenti ai sottoinsiemi del modello racchiusi tra parentesi. Pertanto, se si analizza una stringa contenente una data gg/mm/aa e si desidera inoltre estrarre gli elementi gg, mm, aa di tale data, si utilizzerà il modello (\d\d)/(\d\d)/(\d\d).

Risultati dello script


C:\Data\st-2020\dev\python\cours-2020\python3-flask-2020\venv\Scripts\python.exe C:/Data/st-2020/dev/python/cours-2020/python3-flask-2020/bases/bases_11.py

Résultats(xyz1234abcd,^.*?(\d+).*?$)
('1234',)

Résultats(12 34,^.*?(\d+).*?$)
('12',)

Résultats(abcd,^.*?(\d+).*?$)
La chaîne [abcd] ne correspond pas au modèle [^.*?(\d+).*?$]

Résultats(xyz1234abcd,^(.*?)(\d+)(.*?)$)
('xyz', '1234', 'abcd')

Résultats(12 34,^(.*?)(\d+)(.*?)$)
('', '12', ' 34')

Résultats(abcd,^(.*?)(\d+)(.*?)$)
La chaîne [abcd] ne correspond pas au modèle [^(.*?)(\d+)(.*?)$]

Résultats(10/05/97,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('10', '05', '97')

Résultats( 04/04/01 ,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
('04', '04', '01')

Résultats(5/1/01,^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$)
La chaîne [5/1/01] ne correspond pas au modèle [^\s*(\d\d)\/(\d\d)\/(\d\d)\s*$]

Résultats(187.8,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '187.8')

Résultats(-0.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('-', '0.6')

Résultats(4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4')

Résultats(.6,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '.6')

Résultats(4.,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('', '4.')

Résultats( + 4,^\s*([+-]?)\s*(\d+\.\d*|\.\d+|\d+)\s*$)
('+', '4')

Process finished with exit code 0