Sei sulla pagina 1di 74

GUIDA PYTHON 3

Prof. Fabrizio Montanaro


2020
SOMMARIO
1 INTRODUZIONE ........................................................................................................................... 4
1.1 NASCITA DEL LINGUAGGIO ........................................................................................................................ 4
1.2 I PUNTI DI FORZA DI PYTHON ..................................................................................................................... 4
1.3 COSA SI PUÒ FARE CON PYTHON................................................................................................................. 5
1.4 CHI USA PYTHON .................................................................................................................................... 6
1.5 INSTALLARE PYTHON SU WINDOWS ............................................................................................................ 6

2 L’INTERPRETE PYTHON ................................................................................................................. 7


2.1 ESECUZIONE DA RIGA DI COMANDO............................................................................................................. 7
2.2 ESECUZIONE DI SCRIPT .PY ......................................................................................................................... 7
2.3 USARE THONNY...................................................................................................................................... 8
2.4 GLI ERRORI DI PROGRAMMAZIONE .............................................................................................................. 9
2.5 IL DEBUG ............................................................................................................................................. 10

3 LE FUNZIONI PRINT E INPUT.......................................................................................................... 11


3.1 PRINT ................................................................................................................................................. 11
3.2 INPUT ................................................................................................................................................. 11

4 INDENTAZIONE.......................................................................................................................... 13
4.1 INDENTAZIONE E BLOCCHI DI CODICE ......................................................................................................... 13

5 I COMMENTI............................................................................................................................. 14

6 LE VARIABILI ............................................................................................................................. 15
6.1 DIFFERENZE CON ALTRI LINGUAGGI ........................................................................................................... 15
6.2 TIPI DI DATO ........................................................................................................................................ 16
6.3 TYPE() ................................................................................................................................................ 17
6.4 NOMI DI VARIABILI ................................................................................................................................ 17
6.5 LE COSTANTI ........................................................................................................................................ 17
6.6 ASSEGNAMENTO MULTIPLO .................................................................................................................... 18
6.7 VARIABILI, OGGETTI E REFERENZE ............................................................................................................. 18
6.8 IMMUTABILITÀ ..................................................................................................................................... 19
6.9 CONVERSIONI TRA TIPI ........................................................................................................................... 20

7 OPERATORI .............................................................................................................................. 22
7.1 OPERATORI ARITMETICI .......................................................................................................................... 22
7.2 OPERATORI DI CONFRONTO ..................................................................................................................... 22
7.3 OPERATORI BOOLEANI ........................................................................................................................... 23
7.4 OPERATORI BINARI ................................................................................................................................ 23

8 STRINGHE IN PYTHON................................................................................................................. 24
8.1 INDEXING E SLICING ............................................................................................................................... 24
8.2 CONTENIMENTO ................................................................................................................................... 26
1
8.3 CONCATENAMENTO, RIPETIZIONE E LUNGHEZZA .......................................................................................... 26
8.4 CONFRONTO TRA STRINGHE .................................................................................................................... 26
8.5 FUNZIONI E METODI.............................................................................................................................. 27
8.6 HELP() E DIR() ...................................................................................................................................... 28
8.7 FORMATTAZIONE DELLE STRINGHE ............................................................................................................ 29
8.8 IMMUTABILITÀ DELLE STRINGHE ............................................................................................................... 31

9 ISTRUZIONI CONDIZIONALI ........................................................................................................... 32


9.1 IF-ELIF-ELSE ......................................................................................................................................... 32
9.2 INDENTAZIONE NELL’ISTRUZIONI IF ............................................................................................................ 33
9.3 SOSTITUIRE LO “SWITCH-CASE” ................................................................................................................ 34

10 CICLI: WHILE E FOR .................................................................................................................... 36


10.1 CICLO WHILE ........................................................................................................................................ 36
10.2 CICLO FOR ........................................................................................................................................... 36
10.3 RANGE ................................................................................................................................................ 37
10.4 BREAK E CONTINUE ................................................................................................................................ 37
10.5 FOR-ELSE E WHILE-ELSE .......................................................................................................................... 38

11 LE STRUTTURE DATI.................................................................................................................... 39
11.1 LE LISTE .............................................................................................................................................. 40
11.2 CREAZIONE DI UNA LISTA ........................................................................................................................ 41
11.3 MODIFICA DI UNA LISTA ......................................................................................................................... 41
11.4 RIMUOVERE UN ELEMENTO DA UNA LISTA .................................................................................................. 42
11.5 ULTERIORI FUNZIONI E METODI ................................................................................................................ 42
11.6 ARRAY CON LE LISTE (VETTORI E MATRICI)................................................................................................... 43
11.7 LE TUPLE ............................................................................................................................................. 43
11.8 GLI INSIEMI ......................................................................................................................................... 44
11.9 I METODI DEGLI INSIEMI .......................................................................................................................... 44
11.10 LE OPERAZIONI INSIEMISTICHE ................................................................................................................. 45
11.11 I DIZIONARI .......................................................................................................................................... 45
11.12 ACCESSO AI DATI DI UN DIZIONARIO .......................................................................................................... 46

12 LE FUNZIONI ............................................................................................................................. 47
12.1 LA CHIAMATA DELLA FUNZIONE ................................................................................................................ 47
12.2 I VALORI RESTITUITI ............................................................................................................................... 47
12.3 PARAMETRI FORMALI E ATTUALI ............................................................................................................... 48
12.4 IL PASSAGGIO DEGLI ARGOMENTI AI PARAMETRI ........................................................................................... 48
12.5 VARIABILI GLOBALI E LOCALI .................................................................................................................... 48
12.6 I MODULI ............................................................................................................................................ 49
12.7 I MODULI PREDEFINITI ............................................................................................................................ 50

13 LA GESTIONE DELLE ECCEZIONI...................................................................................................... 51


13.1 L’ISTRUZIONE TRY … EXCEPT .................................................................................................................... 51
13.2 GESTIONE DI SPECIFICHE ECCEZIONI .......................................................................................................... 52
13.3 TIPI DI ERRORE ..................................................................................................................................... 53
2
13.4 ELSE................................................................................................................................................... 54
13.5 FINALLY .............................................................................................................................................. 54
13.6 LE ECCEZIONI E LE FUNZIONI .................................................................................................................... 54
13.7 L’ISTRUZIONE RAISE ............................................................................................................................... 55

14 I FILE ...................................................................................................................................... 56
14.1 DEFINIZIONE DI ARCHIVIO ....................................................................................................................... 56
14.2 OPERAZIONI SUI FILE .............................................................................................................................. 57
14.3 TIPOLOGIE DI FILE ................................................................................................................................. 57
14.4 UTILIZZO DEI FILE DI TESTO IN PYTHON ...................................................................................................... 57
14.5 ACCESSO AI FILE DI TESTO ....................................................................................................................... 58
14.6 LETTURA E SCRITTURA DI UN FILE DI TESTO .................................................................................................. 58
14.7 APERTURA DI UN FILE ............................................................................................................................. 58
14.8 CHIUSURA DEL FILE ................................................................................................................................ 59
14.9 ESEMPIO: CREAZIONE DI UN FILE DI TESTO (METODO WRITE) .......................................................................... 59
14.10 ESEMPIO: LETTURA DI UN FILE DI TESTO (METODO READLINE) ......................................................................... 59
14.11 ESEMPIO: AMPLIAMENTO DI UN FILE DI TESTO (APPEND) ............................................................................... 59
14.12 CARICAMENTO DI UN FILE DI TESTO IN UNA LISTA ......................................................................................... 60
14.13 COME CONTROLLARE SE UN FILE ESISTE? .................................................................................................... 61
14.14 LA GESTIONE DEGLI ERRORI CON I FILE ....................................................................................................... 61
14.15 SALVARE STRUTTURE DATI ALL’INTERNO DI FILE (PICKLE) ................................................................................ 62

15 LA PROGRAMMAZIONE AD OGGETTI ............................................................................................... 63


15.1 LA PROGRAMMAZIONE IMPERATIVA .......................................................................................................... 63
15.2 LA PROGRAMMAZIONE STRUTTURATA........................................................................................................ 63
15.3 LA PROGRAMMAZIONE PROCEDURALE ....................................................................................................... 63
15.4 LA PROGRAMMAZIONE MODULARE ........................................................................................................... 64
15.5 LA PROGRAMMAZIONE AD OGGETTI .......................................................................................................... 65
15.6 VANTAGGI DELLA PROGRAMMAZIONE AD OGGETTI ....................................................................................... 66
15.7 OGGETTI, METODI E MESSAGGI ................................................................................................................ 66
15.8 LA CLASSE ........................................................................................................................................... 67
15.9 INCAPSULAMENTO E INFORMATION HIDING ................................................................................................ 68
15.10 EREDITARIETÀ ...................................................................................................................................... 69
15.11 POLIMORFISMO .................................................................................................................................... 70
15.12 CREAZIONE DI UNA CLASSE ...................................................................................................................... 71
15.13 CREAZIONE DI UN OGGETTO .................................................................................................................... 72
15.14 IL COSTRUTTORE ................................................................................................................................... 72
15.15 IL MODULO DELLA CLASSE ....................................................................................................................... 73
15.16 VISIBILITÀ DEI MEMBRI DI UNA CLASSE ....................................................................................................... 73

3
1 INTRODUZIONE
Python è un linguaggio di programmazione moderno, dalla sintassi semplice e potente che ne facilita
l’apprendimento. Gli ambiti di applicazione di questo linguaggio di programmazione sono svariati: sviluppo di siti
o applicazioni Web e desktop, realizzazione di interfacce grafiche, amministrazione di sistema, calcolo scientifico
e numerico, database, giochi, grafica 3D, eccetera.

1.1 NASCITA DEL LINGUAGGIO

Nei primi anni ottanta, al National Research Institute for Mathematics and Computer Science (CWI) di
Amsterdam, alcuni ricercatori tra cui Guido Van Rossum svilupparono un linguaggio di nome ABC, molto potente
ed elegante, che diventò popolare nel mondo Unix.

Qualche anno dopo (fine anni ottanta) Guido Van Rossum ebbe una serie di idee mirate al miglioramento di ABC,
e pertanto si mise a lavorare allo sviluppo di un nuovo linguaggio: Python.

Nel 2000 Van Rossum e il suo team si trasferiscono presso BeOpen.com e formano i BeOpen PythonLabs team,
con Python giunto alla versione 1.6. Poco tempo dopo viene rilasciata la versione 2.0.

Nel 2001 viene rilasciato Python 2.1, e ridefinita la licenza come “Python Software Foundation License”.

Bisogna arrivare al Dicembre 2008 per assistere ad una vera rivoluzione, con il rilascio della versione 3.0 di Python.

Questa nuova versione, molto simile alla precedente, ha semplificato il linguaggio e introdotto diversi
miglioramenti. Per via di questi cambiamenti Python 3 non è compatibile con Python 2.

Nota: al momento della scrittura di questa guida, l’ultima versione disponibile sul sito www.python.org è la 3.9.

1.2 I PUNTI DI FORZA DI PYTHON

FREE
Python è completamente gratuito ed è possibile usarlo e distribuirlo senza restrizioni di copyright. Nonostante
sia free, da oltre 25 anni Python ha una comunità molto attiva, e riceve costantemente miglioramenti che lo
mantengono aggiornato e al passo coi tempi.

MULTI-PARADIGMA
Python è un linguaggio multi-paradigma, che supporta sia la programmazione procedurale (che fa uso delle
funzioni), sia la programmazione ad oggetti. Inoltre supporta anche diversi elementi della programmazione
funzionale (come iteratori e generatori).

PORTABILE
Python è un linguaggio portabile sviluppato in ANSI C. È possibile usarlo su diverse piattaforme come: Unix, Linux,
Windows, DOS, Macintosh, Sistemi Real Time, OS/2, cellulari Android e iOS. Ciò è possibile perché si tratta di un
linguaggio interpretato, quindi lo stesso codice può essere eseguito su qualsiasi piattaforma purché abbia
l’interprete Python installato.

4
FACILE DA USARE
Python è un linguaggio di alto livello che è al tempo stesso semplice e potente. La sintassi e i diversi moduli e
funzioni che sono già inclusi nel linguaggio sono consistenti, intuitivi, e facili da imparare, e il design del linguaggio
si basa sul principio del least astonishment (cioè della “minor sorpresa”: il comportamento del programma
coincide con quanto ci si aspetta).

RICCO DI LIBRERIE
Ogni installazione di Python include la standard library, cioè una collezione di oltre 200 moduli per svolgere i
compiti più disparati, come ad esempio l’interazione con il sistema operativo e il filesystem, o la gestione di diversi
protocolli. Inoltre, il Python Package Index (www.pypi.org) consente di scaricare ed installare migliaia di moduli
aggiuntivi creati e mantenuti dalla comunità.

PERFORMANTE
Anche se Python è considerato un linguaggio interpretato, i programmi vengono automaticamente compilati in
un formato chiamato bytecode prima di essere eseguiti. Questo formato è più compatto ed efficiente, e
garantisce quindi prestazione elevate. Inoltre, diverse strutture dati, funzioni, e moduli di Python sono
implementati internamente in C per essere ancora più performanti.

GESTISCE AUTOMATICAMENTE LA MEMORIA


Python è un linguaggio di alto livello che adotta un meccanismo di garbage collection che si occupa
automaticamente dell’allocazione e del rilascio della memoria. Questo consente al progammatore di usare
variabili liberamente, senza doversi preoccupare di dichiararle e di allocare e rilasciare spazi di memoria
manualmente (cosa che è invece necessaria in linguaggi di più basso livello come il C).

1.3 COSA SI PUÒ FARE CON PYTHON

La dotazione standard e le librerie di terze parti completano Python con funzionalità che lo rendono uno
strumento duttile in svariati ambiti.

PROGRAMMAZIONE GUI
Con Python è possibile scrivere interfacce grafiche (GUI) usando tutti i maggiori toolkit come ad esempio:
▪ Tkinter: già incluso nella standard library e basato su Tcl/Tk;
▪ PyGtk: basato sul popolare toolkit GTK;
▪ wxPython: un’interfaccia Python per il toolkit wxWidgets.

I programmi che usano questi toolkit sono in grado di essere eseguiti su tutte le maggiori piattaforme (Linux,
Windows, Mac).

SVILUPPO WEB
Esistono svariate possibilità per lo sviluppo Web sia ad alto che a basso livello. Per realizzare siti ed applicazioni
web sono disponibili diversi web framework come ad esempio:
▪ Django: uno dei framework web più popolari, che fornisce diversi strumenti per realizzare siti e webapp;
▪ Flask: un “microframework” che permette si creare rapidamente siti semplici;
▪ Web2py: un altro ottimo framework facile da usare.

5
Il sito ufficiale di Python include un elenco di web framework (completi di una breve descrizione) e una guida che
spiega come usare Python bel web.

La piattaforma Google App Engine permette di avviare le proprie applicazioni Web nell’infrastruttura Google.
App Engine ha un ambiente runtime Python dedicato, che include l’interprete Python e la libreria standard
Python.

ULTERIORI UTILIZZI
È possibile usare Python anche per accedere ai database. La standard library include un’interfaccia per SQLite ed
è anche possibile installare moduli per interfacciarsi con altri database (PostgreSQL, Oracle, MySQL, e altri).

Per la realizzazione di giochi, Pygame è un ottimo framework che ne permette lo sviluppo in modo semplice e
intuitivo.

Per realizzare applicazioni scientifiche, SciPy fornisce un ecosistema di tool per la matematica, le scienze e
l’ingegneria.

1.4 CHI USA PYTHON

Oggi Python viene utilizzato in molte grandi realtà del mercato informatico, tra cui:
▪ la NASA usa Python per lo sviluppo di sistemi di controllo;
▪ Yahoo! ha sviluppato in Python alcuni servizi di internet;
▪ Google, Youtube e Netflix usano Python.

1.5 INSTALLARE PYTHON SU WINDOWS

In questa guida utilizzeremo Python 3: è possibile scaricare liberamente l’ultima versione di Python 3 dal sito
ufficiale (www.python.org/downloads/).

Nella pagina di download è possibile trovare il file .exe per le versioni Windows a 32bit e 64bit. È sufficiente
lanciarlo e seguire i vari passaggi.

È possibile inoltre consultare anche la documentazione ufficiale (https://docs.python.org/3.7).

THONNY
La versione ufficiale di Python contiene sia l’interprete che un editor (IDLE) per cominciare a scrivere i primi
programmi.

Sarebbe meglio, però, utilizzare un ambiente di sviluppo integrato (IDE) che facilita il lavoro del programmatore.

Ne esistono svariati ma si consiglia di installare l’editor Thonny (www.thonny.org).

Nota: l’installazione di Thonny comporta l’installazione automatica di Python (non è necessario farlo prima).

6
2 L’INTERPRETE PYTHON
Con Python è possibile scrivere ed eseguire programmi veri e propri (script) ma anche eseguire singoli comandi
utilizzando un interprete interattivo (shell), caratterizzato dal prompt >>>, che è in grado di leggere e valutare
man mano le espressioni inserite dall’utente.

I programmi Python invece sono caratterizzati da file contenenti le istruzioni e salvati con estensione .py

Vediamo quello che succede quando si esegue un script:


▪ il codice scritto viene scansionato alla ricerca di eventuali errori di sintassi;
▪ se non ci sono errori allora il codice sorgente viene trasformato in bytecode;
▪ per potere eseguire questi bytecode, si utilizza un apposito interprete noto come macchina virtuale Python
(PVM).

2.1 ESECUZIONE DA RIGA DI COMANDO

In questa modalità, digitando dei comandi Python si ottiene subito una risposta:

>>> 5 * 3
15
>>>
>>> a = 5
>>> b = 6
>>> 2 * (a+b) + 3*a
37

2.2 ESECUZIONE DI SCRIPT .PY

Ma come si fa a creare ed eseguire un file Python? Per prima cosa bisogna generare un semplice file di testo e
salvarlo con estensione .py, per esempio, helloworld.py. A questo punto possiamo aprire il file creato con un
qualsiasi editor di testi (Notepad, Notepad++ o simili) oppure (consigliato) utilizzando un apposito editor (thonny,
idle, …) e scrivere all’interno le istruzioni.

Come primo esempio, aggiungiamo al nostro file helloworld.py una sola riga di codice print('Hello
World!') che come risultato stamperà una stringa.

7
2.3 USARE THONNY

Apriamo l’editor Thonny.

Qui si scrive il
codice sorgente
Qui i valori
delle variabili
utilizzate

Qui vengono
mostrati i risultati

Nella parte in alto scriviamo il codice e salviamo il file con il nome helloworld.py.

Eseguendo il codice il risultato verrà mostrato nella parte inferiore (shell).

Nella shell è possibile anche “testare” singoli comandi.

Nell’esempio vengono eseguiti i comandi a=10 e b=20+3, i valori delle variabili a e b sono visualizzati nell’apposito
riquadro.

8
2.4 GLI ERRORI DI PROGRAMMAZIONE

Nella scrittura di un programma attraverso un linguaggio di programmazione si possono incontrare diversi tipi di
errore:
▪ errori lessicali che consistono nell’uso di termini non appartenenti al linguaggio;
▪ errori sintattici che consistono nella costruzione di istruzioni non corrette dal punto di vista delle regole
grammaticali del linguaggio;
▪ errori semantici (o logici) che riguardano la correttezza dell’algoritmo cioè il programma non produce i risultati
attesi;
▪ errori di runtime che si possono verificare durante l’esecuzione del programma, sulla base di particolari valori
assunti dai dati (esempio: divisione per 0).

Vediamo degli esempi.

ERRORE LESSICALE (LA PAROLA IMMETTI NON APPARTIENE AL LINGUAGGIO)


>>> lato=immetti("Inserisci il lato del quadrato: ")
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
NameError: name 'immetti' is not defined

ERRORE SINTATTICO (MANCA IL SECONDO FATTORE DELLA MOLTIPLICAZIONE)


>>> perimetro = lato *
File "<pyshell>", line 1
perimetro = lato *
^
SyntaxError: invalid syntax

ERRORE SEMANTICO (RISULTATO NON CORRETTO)


lato=input("Inserisci il lato del quadrato: ")
perimetro = lato * 4
print(perimetro)

Esecuzione del programma:

Inserisci il lato del quadrato: 3


3333

Il valore visualizzato (3333) è diverso da quello corretto (12) e ciò è dovuto ad un errore logico del codice: non è
stata convertita in intero la stringa acquisita da tastiera con la funzione input ("3") e il programma ha applicato
l’operatore di ripetizione * sulla stringa scrivendo 4 volte il carattere 3.

Gli errori logici riguardano la correttezza dell’algoritmo e non sono rilevabili dall’interprete: è compito del
programmatore controllare che l’output dell’elaborazione corrisponda a risultati corretti.

9
ERRORE DI RUNTIME (DIVISIONE PER ZERO)
a=int(input("Dividendo: "))
b=int(input("Divisore: "))
print("Quoziente:", a/b)

Esecuzione del programma:

Dividendo: 10
Divisore: 0
Traceback (most recent call last):
ZeroDivisionError: division by zero

Eseguendo il programma e introducendo il valore zero come divisore, il programma si interrompe e sul video
compare un messaggio di errore (division by zero).

Il programma, pur essendo scritto secondo le regole del linguaggio Python, si blocca perché ha incontrato una
situazione di errore durante la sua esecuzione.

2.5 IL DEBUG

Il programma di utilità che aiuta il programmatore nell’individuazione degli errori logici si chiama debugger.

Un debugger consente di:

▪ eseguire il programma un’istruzione per volta in modo da verificarne la corretta evoluzione;


▪ stabilire dei punti di interruzione (breakpoint) durante l’esecuzione per effettuare dei controlli;
▪ eseguire normalmente il programma fino al primo punto di interruzione;
▪ controllare i valori assunti dalle variabili durante l’esecuzione del programma.

All’interno dell’ambiente di sviluppo Thonny è possibile:

▪ attivare la modalità di debug cliccando sul pulsante ;

▪ eseguire il programma passo-passo con gli appositi pulsanti ;

▪ visualizzare il valore delle variabili durante l’esecuzione del debug;

▪ inserire breakpoint ( ) facendo doppio-click a destra del numero della riga in cui inserire l’interruzione;

▪ interrompere il debug con il pulsante .

10
3 LE FUNZIONI PRINT E INPUT
Vediamo due funzioni basilari di Python: print e input.

Queste funzioni servono rispettivamente a mostrare (output) e a chiedere (input) valori all’utente.

3.1 PRINT

La funzione print serve a “stampare” in output (tipicamente sullo schermo, ma volendo anche su file o altri
stream) il valore di una variabile o di una espressione.

>>> a = 12
>>> b = 3
>>> print(a, b, a-b)
12 3 9
>>>
>>> c = 'Hello'
>>> print(c, 'World!')
Hello World!

Si può notare che la funzione print accetta in input un numero variabile di argomenti (anche di tipi diversi), li
converte in stringhe, e li mostra in output separati da uno spazio e seguiti da un carattere di ritorno a capo (\n);
consente inoltre di specificare il separatore, il carattere finale, lo stream, e altri parametri.

Quando si lavora dall’interprete interattivo non è necessario utilizzare print per vedere il valore di una variabile
o espressione, ma è sufficiente digitarla:

>>> x = 10
>>> x
10
>>> x * 2
20

Questa possibilità è disponibile solo dall’interprete interattivo; quando si esegue un programma, invece, è
necessario utilizzare print esplicitamente.

La funzione print va a capo automaticamente. Per rimanere sulla stessa linea occorre scrivere:

print("…", end="")

3.2 INPUT

La funzione input viene usata per consentire all’utente di immettere dati da tastiera, che verranno poi utilizzati
dal programma.

input accetta un singolo argomento opzionale: una stringa che viene mostrata a video prima di leggere il valore
digitato.

11
Una volta che l’utente ha digitato un valore e premuto il tasto Invio, input restituisce il valore come stringa,
come mostra il seguente esempio:

>>> nome = input('Inserisci il tuo nome: ')


Inserisci il tuo nome: Ezio
>>> nome
'Ezio'

In questo esempio possiamo vedere che:


▪ la stringa passata a input che chiede di inserire il nome viene mostrata a video;
▪ input attende che l’utente digiti il nome (Ezio) e prema Invio;
▪ input restituisce il nome inserito come stringa;
▪ la stringa restituita da input viene assegnata alla variabile nome;
▪ la variabile nome può poi essere utilizzata per accedere al nome inserito dall’utente.

Se si desidera immettere valori numerici o di altri tipi, è necessario convertire la stringa restituita da input usando
funzioni come int() o float():

>>> raggio = input('Inserisci il raggio: ')


Inserisci il raggio: 8.4
>>> r = float(raggio)
>>> raggio, r
('8.4', 8.4)
>>> print('Area:', 3.14 * r**2)
Area: 221.5584
>>> print('Circonferenza:', 2 * 3.14 * r)
Circonferenza: 52.752

In questo esempio possiamo vedere che:


▪ input chiede all’utente di inserire un raggio che viene assegnato alla variabile raggio;
▪ la funzione float viene usata per convertire raggio (che è una stringa) in un valore numerico con la virgola
che viene assegnato alla variabile r;
▪ le due variabili (raggio e r) vengono stampate per mostrare che la prima è una stringa (quindi rappresentata
tra '...') mentre la seconda è un numero;
▪ r viene poi usata per calcolare l’area del cerchio (** è l’operatore di elevazione a potenza) e la funzione print
viene usata per stampare la stringa 'Area:' e il risultato dell’espressione 3.14 * r**2;
▪ r viene usata anche per calcolare la circonferenza e print per stampare la stringa 'Circonferenza:' e il risultato
dell’espressione 2 * 3.14 * r.

12
4 INDENTAZIONE
Vediamo più in dettaglio uno degli aspetti fondamentali della programmazione con Python: l’indentazione.

4.1 INDENTAZIONE E BLOCCHI DI CODICE

A differenza di altri linguaggi che delimitano blocchi di codice con parentesi graffe (come C, C++ e Java) o con
parole riservate come begin/end, Python usa l’indentazione.

Indentare il codice è una pratica comune in tutti i linguaggi, perché semplifica la lettura del codice e la
comprensione della sua struttura.

Anzichè usare due meccanismi separati per compilatori/interpreti (parentesi o keyword) e persone
(indentazione), per Python si è scelto di usare l’indentazione per entrambi.

Questa scelta ha diversi aspetti positivi, tra cui:


▪ il linguaggio risulta più chiaro e leggibile;
▪ la struttura del programma coincide sempre con quella dell’indentazione;
▪ lo stile di indentazione è necessariamente uniforme in qualsiasi listato.

Questo significa che, in Python, l’indentazione è significativa, e che indentare in modo incorretto può portare a
comportamenti sbagliati del programma o a errori.

Vediamo un semplice esempio (usiamo il costrutto if, che approfondiremo successivamente).

print("eseguito sempre all'inizio")


if condizione:
print('eseguito in mezzo solo se la condizione è vera')
print('eseguito in mezzo solo se la condizione è vera')
print('eseguito in mezzo solo se la condizione è vera')
print('eseguito sempre alla fine')

In questo esempio possiamo vedere che:


▪ il primo print, l’if, e l’ultimo print hanno lo stesso livello di indentazione, e vengono eseguiti sempre;
▪ dopo l’if c’è un blocco di codice con un livello di indentazione maggiore, che include tre print;
▪ se la condizione dell’if è vera, i tre print vengono eseguiti;
▪ se la condizione dell’if è falsa, i tre print non vengono eseguiti.

È quindi molto importante fare attenzione all’indentazione, perché viene sempre valutata nel processo di parsing
del programma.

13
5 I COMMENTI
In Python è possibile usare il carattere # per aggiungere commenti al codice.

Ogni riga di commento deve essere preceduta da un # ed è anche possibile aggiungere commenti in seguito a
istruzioni:

# Questo commento occupa diverse righe, e ogni riga


# è preceduta da un # per indicare a Python di
# ignorarle tutte
a = 3 # questo commento segue un'istruzione

Python ignorerà automaticamente tutto ciò che segue il carattere # fino al termine della riga.

Commentare il codice durante il lavoro di programmazione permette di raggiungere due importanti obiettivi:

▪ far comprendere l’analisi del procedimento e l’algoritmo risolutivo a una persona diversa da quella che lo ha
progettato;
▪ riuscire a capire il procedimento e le attività da svolgere anche a distanza di tempo dal momento in cui il
programma è stato realizzato.

Per questo motivo è importante (se non obbligatorio!) inserire frequenti frasi di commento per illustrare i diversi
passaggi del programma oppure il significato di particolari variabili.

Un’altra cosa fondamentale è quella di usare per le variabili dei nomi significativi cioè che servono a ricordare
l’entità che rappresentano.

14
6 LE VARIABILI
Per definire variabili in Python, è sufficiente utilizzare l’operatore di assegnamento (=) come nei seguenti esempi:

numero = 10
stringa = "Python"
lista = [1, 2, 3]

Come si vede, in Python non è necessario né definire le variabili prima di utilizzarle, né specificare il loro tipo.

6.1 DIFFERENZE CON ALTRI LINGUAGGI

In linguaggi come C, le variabili fanno riferimento a specifiche locazioni di memoria che hanno una dimensione
fissa che dipende dal loro tipo (per questo è necessario specificare il tipo quando si dichiara una variabile).

In Python invece, gli oggetti hanno un tipo specifico (numero, stringa, lista, etc.), e le variabili sono solo
“etichette” che si si riferiscono a un determinato oggetto.

Per capire meglio questo fondamentale concetto, possiamo vedere un semplice esempio.

/* Codice C */
int x;
x = 10;
x = 20;

In questo codice C:
▪ viene definita una variabile x di tipo int (cioè grande abbastanza per contenere un numero intero);
▪ il valore 10 viene salvato nella locazione di memoria associata a x;
▪ il valore 20 viene salvato nella locazione di memoria associata a x, sovrascrivendo il 10.

Vediamo invece cosa succede con Python:

# codice Python
x = 10
x = 20

Anche se questo codice Python può sembrare molto simile, quello che accade è diverso:
▪ l’oggetto 10 viene creato in memoria, e l’operazione di assegnamento fa in modo che la variabile x si riferisca
a questo oggetto;
▪ un nuovo oggetto 20 viene creato, sempre nella memoria, e la variabile x viene “spostata” da 10 a 20;
▪ siccome non ci sono più variabili che fanno riferimento all’oggetto 10, il garbage collector lo eliminirà
automaticamente dalla memoria.

Ovviamente, in entrambi questi esempi, il valore finale associato con la variabile x sarà 20.

15
Come abbiamo detto precedentemente, in Python le variabili non hanno tipo e possono riferirsi a qualsiasi tipo
di oggetto.

Il codice seguente è quindi perfettamente valido in Python:

x = 10
x = "Python"
x = [1, 2, 3]

In questo esempio la variabile x viene “spostata” dall’intero 10 alla stringa "Python" e infine alla lista [1, 2, 3].

6.2 TIPI DI DATO

Python possiede sia i classici tipi di dato, comuni alla maggior parte dei linguaggio di programmazione, ma anche
diversi tipi più potenti e flessibili.

Ecco una tabella che elenca alcuni dei tipi di dati più comuni in Python:

TIPO DI DATO NOME DESCRIZIONE ESEMPI

-42, 0, 1200,
Intero int Intero di dimensione arbitraria 999999999999999999

Reale float Numero a virgola mobile 3.14, 1.23e-10, 4.0E210

Booleano bool Per valori veri o falsi True, False

Numeri complessi con parte reale e


Complesso complex 3+4j, 5.0+4.1j, 3j
immaginaria

Stringhe str Usata per rappresentare testo '', 'stefano', "l'acqua"

[], [1, 2, 3], ['Hello',


Liste list Una sequenza mutabile di oggetti 'World']

(), (1, 2, 3), ('Python',


Tuple tuple Una sequenza immutabile di oggetti 3)

{1, 2, 3}, {'World',


Insiemi set Un’insieme di oggetti unici 'Hello'}

{}, {'nome': 'Mario',


Dizionari dict Una struttura che associa chiavi a valori 'cognome': 'Rossi'}

Successivamente affronteremo più in dettaglio questi tipi di dato e vedremo le loro caratteristiche.

16
6.3 TYPE()

La funzione type() restituisce il tipo (class) di un oggetto:

>>> a=10
>>> type(a)
<class 'int'>
>>> b=12.3
>>> type(b)
<class 'float'>
>>> c=True
>>> type(c)
<class 'bool'>
>>> s="computer"
>>> type(s)
<class 'str'>
>>> q='c'
>>> type(q)
<class 'str'>

Nota: anche il singolo carattere è considerato di tipo stringa (class str).

6.4 NOMI DI VARIABILI

Ricordiamo che le regole da seguire nella scelta dei nomi delle variabili è simile a quella dei più comuni linguaggi
di programmazione, in particolare:
▪ ogni nome di variabile deve iniziare con una lettera o con il carattere underscore (_), e può essere seguita da
lettere, numeri, o underscore;
▪ esistono delle parole riservate (keyword) che non possono essere utilizzate come nomi di variabili: False,
None, True, and, as, assert, break, class, continue, def, del, elif, else,
except, finally, for, from, global, if, import, in, is, lambda, nonlocal,
not, or, pass, raise, return, try, while, with, yield;
▪ Python è un linguaggio case-sensitive, che distingue tra nomi di variabili composti da caratteri minuscoli e
maiuscoli;
▪ in Python 3 è possibile (ma generamente sconsigliato) usare caratteri accentati o in altri alfabeti nei nomi delle
variabili, ad esempio: età = 20.

6.5 LE COSTANTI

Nel linguaggio Python non esiste un modo specifico per dichiarare delle costanti ma, semplicemente, vengono
utilizzate le variabili.

Nella consuetudine della programmazione, le costanti sono rappresentate con identificativi scritti in maiuscolo,
ad esempio:

>>> PERC=20
>>> PIGRECO=3.14
>>> PREFISSO="0341"

17
6.6 ASSEGNAMENTO MULTIPLO

Una singolare possibilità offerta da Python è rappresentata dall’assegnamento multiplo, che permette di
inizializzare più variabili direttamente sulla stessa riga di codice.

Per capire quest’ultimo concetto, basta osservare l’esempio seguente:

>>> a, b, c = 2, 3, 5 # assegnamento multiplo


>>> a * b + c
11
>>> a
2
>>> b
3
>>> c
5

6.7 VARIABILI, OGGETTI E REFERENZE

Come abbiamo visto, Python adotta la tipizzazione dinamica: i tipi vengono determinati automaticamente
durante l’esecuzione delle istruzioni.

Vediamo più in dettaglio come interpretare correttamente un’assegnazione, ad esempio:


>>> a=18

 Viene creato un oggetto (che nel nostro caso coincide con


l’intero 18) e conservato in memoria;
 viene creato il nome a (nel caso in cui non esista già);
 viene creato un collegamento (referenza) che partendo da
a, punta alla locazione di memoria che contiene l’oggetto.

È possibile ottenere l’indirizzo di memoria dell’oggetto a cui si rifersisce una variabile con la funzione id.

>>> id(a)
1674177168

Quindi:
▪ ogni oggetto possiede un suo tipo, indipendentemente dal fatto che vi sia un’assegnazione;
▪ se assegniamo un oggetto a una variabile, essa assume il tipo dell’oggetto a cui si riferisce;
▪ la nozione di tipo risiede nell’oggetto e non nella variabile che si riferisce all’oggetto.

18
Vediamo ora cosa succeede con le seguenti assegnazioni successive:

>>> b=a
>>> a=13

 Viene ricercato l’oggetto associato al nome a (cioè l’intero


18);
 viene creato il nome b (nel caso in cui non esista già);
 viene creato un collegamento (referenza) che partendo da
b, punta alla locazione di memoria che contiene l’oggetto
18. A questo livello, i due nomi a e b puntano alla stessa area
di memoria!

 viene creato e conservato in memoria l’intero 13;


 al nome a viene assegnata una referenza alla locazione di
memoria che contiene il nuovo oggetto 13.

È possibile verificare andando a visualizzare gli indirizzi di memoria a cui si riferiscono le variabili a e b:

>>> id(b) # stesso indirizzo che aveva a


1674177168
>>> id(a) # nuovo indirizzo di a
1674177328

6.8 IMMUTABILITÀ

Il meccanismo visto precedentemente viene indicato in Python con il termine immutabilità: un oggetto (in
memoria) è immutabile se non è possibile modificarne il contenuto e quindi ogni volta verrà creato (come negli
esempio visti) un nuovo oggetto.

In Python esistono oggetti mutabili e immutabili:

OGGETTI IMMUTABILI OGGETTI MUTABILI

Numerici: int, float, complex Liste: list

Booleani: bool Insiemi: set

Stringhe: str Dizionari: dict

Tuple: tuple

Quando lavoriamo con oggetti mutabili (ad esempio le liste), vi sono operazioni che li modificano “sul posto”
anzichè creare nuovi oggetti. In tal caso occorre fare particolare attenzione agli oggetti condivisi da due o più
variabili.
19
Consideriamo il seguente esempio:

>>> L1=[1,2,3] # ho creato una lista


>>> L2=L1
>>> L1[1]=4 # modifico un elemento della lista

 Alla variabile L1 viene assegnata la lista [1, 2, 3];


 la variabile L2 referenzia lo stesso oggetto referenziato dalla
variabile L1;

 Modifichiamo "in place" un elemento della lista. La modifica


si riflette anche sulla variabile L2!

6.9 CONVERSIONI TRA TIPI

Per capire il meccanismo della conversione (casting) tra tipi partiamo da un esempio:

>>> a=10
>>> type(a)
<class 'int'>

La variabile a, dopo l’assegnamento del numero intero 10, è ovviamente di tipo int.

Effettuiamo ora la seguente operazione:

>>> a=a+2/5
>>> type(a)
<class 'float'>
>>> a
10.4

La variabile a è diventata di tipo float in quanto è stato aggiunto il risultato della divisione 2/5 che restituisce un
numero reale: in questo caso è avvenuta una conversione implicita.

In altri casi, al fine di evitare risultati non desiderati, è necessario effettuare una conversione esplicita utilizzando
apposite funzioni: un caso molto utile è quello di convertire delle stringhe che riportano numeri in int o float (lo
abbiamo già visto nel caso della funzione input).

Per convertire una stringa in interi si utilizza la funzione int(), passando la stringa da convertire come
argomento della funzione mentre per convertire una stringa in float si utilizza la funzione float(): ovviamente
ciò sarà possibile solo se la stringa rappresenti un numero adatto alla conversione.

20
Vediamo un esempio in cui non convertire esplicitamente porta ad errori di calcolo:

>>> a='27'
>>> b=a*3
>>> b
'272727'

Il problema è dovuto al fatto che l’operatore * utilizzato con le stringhe non effettua la moltiplicazione ma la
ripetizione! Per risolvere è necessario utilizzare la funzione int():

>>> b=int(a)*3
>>> b
81

Una stringa da convertire in numero docrà essere scritta in maniera corretta e non contenere caratteri non
numerici altrimenti verrà generato un errore:

>>> s='10a'
>>> b=int(s)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
ValueError: invalid literal for int() with base 10: '10a'

>>> s='10,23'
>>> b=float(s)
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
ValueError: could not convert string to float: '10,23'

Se si converte un numero reale in intero viene troncata la parte decimale (nessun arrotondamento):

>>> a=10.95
>>> b=int(a)
>>> b
10

È possibile anche convertire tipi numerici in stringhe utilizzando la funzione str().

>>> a=str(10/3)
>>> a
'3.3333333333333335'

21
7 OPERATORI
Vediamo i vari operatori che è possibile utilizzare nel linguaggio Python.

7.1 OPERATORI ARITMETICI

Le operazioni sui tipi numerici sono le più classiche:

OPERATORE DESCRIZIONE ESEMPI

+ addizione 10 + 12 → 22

- sottrazione 5 - 1 → 4

* moltiplicazione 10 * 12 → 120

/ divisione (restituisce un float) 9 / 4 → 2.25

// divisione intera 9 // 4 → 2

% modulo (resto della divisione intera) 9 % 4 → 1

7.2 OPERATORI DI CONFRONTO

Python supporta anche operatori di confronto, che restituiscono True o False:

OPERATORE DESCRIZIONE ESEMPI

+ addizione 10 + 12 → 22

- sottrazione 5 - 1 → 4

* moltiplicazione 10 * 12 → 120

/ divisione (restituisce un float) 9 / 4 → 2.25

// divisione intera 9 // 4 → 2

% modulo (resto della divisione intera) 9 % 4 → 1

22
7.3 OPERATORI BOOLEANI

In Python esistono anche gli operatori booleani and, or, e not:

OPERATORE DESCRIZIONE ESEMPI

Ritorna True se entrambi gli operandi sono 10>8 and 6<8 → True
and
veri, altrimenti False 10>8 and 6>8 → False

Ritorna True se almeno uno degli operandi è 10>8 or 6>8 → True


or 10<8 or 6>8 → False
vero, altrimenti False
Ritorna False se l’operando è vero, True se
not not(10<8) → True
l’operando è falso

In Python ogni oggetto può essere:


▪ vero (numeri diversi da 0, la costante True, o contenitori che contengono almeno un elemento);
▪ falso (ovvero il numero 0, le costanti False e None, contenitori vuoti).

Così come avviene in altri linguaggi di programmazione, anche in Python gli operatori and e or funzionano in
modo che, se il primo operando è sufficiente a determinare il risultato, il secondo non viene valutato.

7.4 OPERATORI BINARI

Esistono poi gli operatori binari (o bitwise) che permettono di lavorare al livello dei singoli bit e sono utili in
particolari circostanze:

OPERATORE DESCRIZIONE

x << n esegue uno shift a sinistra di n posizioni dei bit di x

x >> n esegue uno shift a destra di n posizioni dei bit di x

x & y esegue un and tra i bit di x e di y

x | y esegue un or tra i bit di x e di y

x ^ y esegue un or esclusivo tra i bit di x e di y

~x inverte i bit di x

23
8 STRINGHE IN PYTHON
Per dichiarare una stringa è sufficiente assegnare ad una nuova variabile un testo racchiuso tra virgolette: è
possibile racchiudere il suo valore indifferentemente tra apici (carattere ') o doppi apici (carattere ").

Questo permette di superare facilmente il problema dell’utilizzo dei suddetti caratteri nel valore stesso della
stringa, ad esempio "l'acqua" oppure 'Egli disse: "Acqua"'.

Le stringhe sono un tipo particolare di sequenza (di caratteri) e supporta tutte le operazioni comuni alle sequenze
(che rivedremo nelle tuple e nelle liste), vediamone alcune.

8.1 INDEXING E SLICING

In Python, è possibile accedere agli elementi di una stringa, usando la sintassi nome_stringa[indice].

Questo restituirà l’elemento in posizione indice (il primo elemento ha sempre indice 0). È inoltre possibile
specificare indici negativi che partono dalla fine della stringa (l’ultimo elemento ha indice -1, il penultimo -2, ecc.).

Questa operazione è chiamata indexing.

>>> s = 'Python'
>>> s[0] # elemento in posizione 0 (il primo)
'P'
>>> s[5] # elemento in posizione 5 (il sesto)
'n'
>>> s[-4] # elemento in posizione -4 (il quartultimo)
't'

Se si usa come indice un valore superiore alla lunghezza della stringa si ottiene un messaggio di errore:

>>> s[10]
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
IndexError: string index out of range

La sintassi stringa[inizio:fine] ci permette invece di ottenere una nuova stringa dello stesso tipo che
include tutti gli elementi partendo dall’indice inizio (incluso) all’indice fine (escluso).

Se inizio è omesso, gli elementi verranno presi dall’inizio, se fine è omesso, gli elementi verranno presi fino alla
fine. Questa operazione è chiamata slicing (letteralmente “affettare”).

>>> s = 'Python'
>>> s[0:2] # sottostringa con elementi da 0 (incluso) a 2 (escluso)
'Py'
>>> s[:2] # dall'inizio all'elemento con indice 2 (escluso)
'Py'
>>> s[3:5] # dall'elemento con indice 3 (incluso) a 5 (escluso)
'ho'
>>> s[4:] # dall'elemento con indice 4 (incluso) alla fine
'on'
>>> s[-2:] # dall'elemento con indice -2 (incluso) alla fine
'on'
24
Per capire bene il funzionamento delle operazioni di indexing e slicing è utile utilizzare uno schema come negli
esempi successivi.

INDEXING (I CARATTERI SONO NUMERATI A PARTIRE DA 0)

s[5]='A' #cioè il carattere a destra del numero 5

INDEXING (UTILIZZO DI INDICI NEGATIVI)

s[-1]='I' #cioè il carattere a destra del numero -1


s[-6]='M' #cioè il carattere a destra del numero -6

SLICING (UTILIZZO DI INDICI POSITIVI)

s[3:6]='REA' #caratteri contenuti tra 3 e 6


s[:4]='ANDR' #caratteri contenuti tra l’inizio della stringa e 4
s[9:]='NINI' #caratteri contenuti tra 9 e la fine della stringa

SLICING (UTILIZZO DI INDICI NEGATIVI)

s[-10:-7]='REA' #caratteri contenuti tra -10 e -7


s[-4:]='NINI' #caratteri contenuti -4 e la fine
s[:-7]='ANDREA' #caratteri contenuti tra l’inizio e -7

25
8.2 CONTENIMENTO

Gli operatori in e not in possono essere usati per verificare se un elemento fa parte di una stringa oppure no.

È anche possibile verificare se una sottostringa è contenuta in una stringa:

>>> s = 'Python'
>>> 'P' in s # controlla se il carattere 'P' è contenuto nella stringa s
True
>>> 'x' in s # il carattere 'x' non è in s, quindi ritorna False
False
>>> 'x' not in s # "not in" esegue l'operazione inversa
True
>>> 'Py' in s # controlla se la sottostringa 'Py' è contenuto nella stringa s
True
>>> 'py' in s # il controllo è case-sensitive, quindi ritorna False
False

8.3 CONCATENAMENTO, RIPETIZIONE E LUNGHEZZA

È possibile usare l’operatore + per concatenare stringhe, e * per ripetere stringhe:

>>> 'Py' + 'thon'


'Python'
>>> 'Py' * 2
'PyPy'
>>> 'Ba' + 'na' * 2
'Banana'

La funzione len() può essere usata per ottenere il numero di caratteri in una stringa:

>>> len('Python')
6
>>> s = 'Precipitevolissimevolmente'
>>> len(s)
26

8.4 CONFRONTO TRA STRINGHE

È possibile verificare l’eguaglianza tra due stringhe mediante l’operatore ==.

Gli operatori < e > verificano la precedenza alfabetica tra le stringhe (utilizzando la tabella Unicode):

>>> amico1="mario"
>>> amico2="MARIO"
>>> print(amico1==amico2)
False
>>> print(amico1>amico2)
False
>>> print(amico1<amico2)
True

26
8.5 FUNZIONI E METODI

Abbiamo già visto alcune funzioni come len(). Le funzioni accettano 0 o più argomenti e possono essere usate
con oggetti di diversi tipi, usando la sintassi funzione(argomenti).

I metodi sono simili alle funzioni ma sono legati al tipo dell’oggetto e hanno una sintassi diversa:
oggetto.metodo(argomenti). Così come le funzioni, i metodi possono accettare 0 o più argomenti.

In questo esempio vengono utilizzati due metodi forniti dal tipo str, che non sono disponibili per altri tipi:

>>> s = 'Python'
>>> s.upper() # il metodo upper ritorna una nuova stringa tutta uppercase
'PYTHON'
>>> s.lower() # il metodo lower ritorna una nuova stringa tutta lowercase
'python'

Di seguito altri esempi di funzioni e metodi che possono essere utilizzati con le stringhe.

FUNZIONI ORD() E CHR()


>>> # ord – valore unicode corrispondente a un carattere
>>> ord('A')
65
>>> ord('a')
97
>>> # chr – carattere corrispondente ad un codice unicode
>>> chr(66)
'B'

METODO CAPITALIZE() converte in maiuscolo il primo carattere di una stringa

>>> 'presidente'.capitalize()
'Presidente'

METODO COUNT() conta le occorrenze di una sottostringa

>>> 'programma'.count('r')
2

METODO REPLACE() sostituisce certe sequenze con altre

>>> '0123ab----ab'.replace('ab','cd')
'0123cd----cd'

METODO FIND() cerca un carattere o una sottostringa all’interno di una stringa e ne restituisce la posizione se la
trova altrimenti restituisce -1.

>>> '0123ab----ab'.find('ab') # cerca dall’inizio


4
>>> '0123ab----ab'.find('ab',5) # cerca a partire dalla posizione 5
10

METODO INDEX() funziona come il metodo find ma se genera un errore se non trova la sottostringa.

>>> '0123ab----ab'.index('-')
6

27
8.6 HELP() E DIR()

Due strumenti particolarmente utili per lavorare con funzioni e metodi sono le funzioni help() e dir():
▪ help(oggetto) restituisce una breve spiegazione riguardo all’oggetto passato come argomento;
▪ dir(oggetto) restituisce una lista di metodi e attributi dell’oggetto.

Vediamo degli esempi:

>>> len # len è una funzione built-in


<built-in function len>

>>> help(len) # si può passare len a help() per vedere una breve spiegazione
Help on built-in function len in module builtins:
len(obj, /)
Return the number of items in a container.

>>> dir(str) # restituisce una lista di metodi e attributi di str


[..., 'capitalize', 'casefold', 'center', 'count', 'encode', 'endswith',
'expandtabs',
'find', 'format', 'format_map', 'index', 'isalnum', 'isalpha', 'isdecimal',
'isdigit',
'isidentifier', 'islower', 'isnumeric', 'isprintable', 'isspace', 'istitle',
'isupper',
'join', 'ljust', 'lower', 'lstrip', 'maketrans', 'partition', 'replace', 'rfind',
'rindex', 'rjust', 'rpartition', 'rsplit', 'rstrip', 'split', 'splitlines',
'startswith', 'strip', 'swapcase', 'title', 'translate', 'upper', 'zfill']

>>> str.upper # upper è un metodo di str


<method 'upper' of 'str' objects>

>>> help(str.upper) # si può passare a help() per vedere una breve spiegazione
Help on method_descriptor:
upper(...)
S.upper() -> str
Return a copy of S converted to uppercase.

Questi strumenti vi consentono di esplorare interattivamente funzioni e metodi e capirne il funzionamento:

>>> help(str.replace) # visualizza l'help per il metodo str.replace


Help on method_descriptor:
replace(...)
S.replace(old, new[, count]) -> str
Return a copy of S with all occurrences of substring
old replaced by new. If the optional argument count is
given, only the first count occurrences are replaced.

>>> 'Python'.replace('thon', 'Py') # sostituisce 'thon' con 'Py' in 'Python'


'PyPy'

>>> s = 'Python, Python, Python!'


>>> s.replace('thon', 'Py', 2) # come sopra, ma massimo 2 sostituzioni
'PyPy, PyPy, Python!'

La documentazione ufficiale di Python include una sezione sui metodi delle stringhe
(https://docs.python.org/3.7/library/stdtypes.html#string-methods).

28
8.7 FORMATTAZIONE DELLE STRINGHE

Nel linguaggio Python il metodo format() consente la formattazione dei dati in una stringa attraverso la
seguente sintassi:

stringa.format(x1,x2,…)

I parametri della funzione format sono i valori da inserire nei relativi campi della stringa indicati da appositi
segnaposti (placeholder) racchiusi tra una coppia di parentesi graffe {…}.

Vediamo un esempio:

stringa="è meglio {} oppure {}?"

Poi stampiamo la stringa con il metodo format() indicando il valore dei due parametri tra parentesi. Ogni
valore è separato dagli altri tramite una virgola.

print(stringa.format("la pizza", "il gelato"))

Il primo parametro "la pizza" è assegnato al primo segnaposto e il secondo parametro "il gelato" è assegnato al
secondo segnaposto.

Il metodo format() costruisce la stringa, sostituendo i segnaposto con i relativi valori, e la funzione print la
visualizza sulla console. Si ottiene quindi:

è meglio la pizza oppure il gelato?

Per formattare un segnaposto, devo aggiungere, dopo la prima parentesi graffa, il carattere : (due punti). A destra
dei due punti posso inserire una specifica di formattazione, ad esempio:

TIPO DESCRIZIONE

:> allineamento a destra

:< allineamento a sinistra

:^ allineamento centrato

:d numeri interi

:f numeri reali

:e numeri reali in notazione scientifica

:b valore binario

:s stringhe

29
Oltre al tipo di dato da visualizzare è possibile specificare il numero di posizioni occupate dal dato oppure, per i
tipi float, il numero di cifre decimali da visualizzare.

Vediamo degli esempi:

print("5 in binario è {:b}".format(5)) # 5 in binario è 101


print("Totale = {:.2f}".format(1234.56789)) # Totale = 1234.57
print("Totale = {:10.2f}".format(1234.56789)) # Totale = 1234.57
print("Totale = {:<10.2f}".format(1234.56789)) # Totale = 1234.57
print("Totale = {:010.2f}".format(1234.56789)) # Totale = 0001234.57
print("Nome = {:>15s}".format('Mario') # Nome = Mario
print("{:*^20}".format("ciao")) # ********ciao********

Nota: nel caso delle stringhe, la specifica s può essere omessa.

Spesso la visualizzazione riguarda più dati: in questi casi occorre usare più segnaposti che vengono associati ai
dati mediante un indice che inizia da 0, scritto nel formato prima del carattere due punti.

L’indice è posizionale, nel senso che il formato con indice 0 è associato al primo dato specificato, l’indice 1 al
secondo e così via.

Vediamo degli esempi.

STRINGHE
>>> cognome="Rossi"
>>> nome="Mario"
>>> print("{0:20} {1:45}".format(cognome,nome))
Rossi Mario

NUMERI INTERI
>>> a=10
>>> print("{0:3d} {1:5d} {2:10d}".format(a,a*2,a*3))
10 20 30

NUMERI FLOAT
>>> n=5
>>> prezzo=12.3
>>> tot=n*prezzo
>>> print("Pezzi={0:4d} - Prezzo={1:8.2f} - Totale={2:8.2f}".format(n,prezzo,tot))
Pezzi= 5 - Prezzo= 12.30 - Totale= 61.50

Per una descrizione completa delle specifiche di formato è possibile consultare la documentazione ufficiale
(https://docs.python.org/3.7/library/string.html#format-specification-mini-language).

30
8.8 IMMUTABILITÀ DELLE STRINGHE

Abbiamo già visto come le stringhe siano oggetti immutabili.

Questo significa che non è possibile modificare un singolo carattere di una stringa:

>>> s='python'
>>> s[0]='P'
Traceback (most recent call last):
File "<pyshell>", line 1, in <module>
TypeError: 'str' object does not support item assignment

Nell’esempio si è cercato di modificare il primo carattere da 'p' (minuscola) a 'P' (maiuscola) ottenendo però un
errore in quanto non è possibile modificare un singolo carattere di una stringa.

Il risultato voluto si sarebbe potuto ottenere in questo modo:

>>> s='python'
>>> s='P'+s[1:]
>>> s
'Python'

In questo caso è stato creato in memoria un nuovo oggetto ('P'+s[1:]) che, successivamente, è stato assegnato
nuovamente ad s e questa cosa è ovviamente permessa.

La variabile s vale quindi 'Python' e si potrebbe, erroneamente, pensare che abbiamo mutato la stringa di
partenza ma in realtà ciò che è avvenuto è che la variabile s si riferisce ad un nuovo oggetto in memoria!

31
9 ISTRUZIONI CONDIZIONALI
Vediamo ora come implementare istruzioni condizionali in Python usando il costrutto if-elif-else. Le
istruzioni condizionali vengono utilizzate quando vogliamo eseguire un blocco di codice solo nel caso in cui una
condizione sia vera o falsa.

9.1 IF-ELIF-ELSE

Il costrutto if-elif-else permette di eseguire istruzioni o gruppi di istruzioni diverse a seconda del
verificarsi di una o più condizioni.

La forma più semplice prevede l’uso di un if seguito da una condizione, dai due punti (:) e da un blocco di codice
indentato che viene eseguito solo se la condizione è vera:

if condizione:
# gruppo di istruzioni eseguite
# se la condizione è vera

Per esempio, per calcolare il valore assoluto di un numero, possiamo procedere così:

n = int(input('Inserisci un numero: '))


if n < 0:
n = -n # se il numero è negativo rendilo positivo
print('Il valore assoluto è', n)

In questo caso il blocco di codice indentato sotto l’if (cioè n = -n) è eseguito solo se il numero è negativo. Se il
numero è invece positivo, il programma procede ad eseguire l’istruzione che segue l’if, cioè il print().

Aggiungendo un else seguito dai due punti (:) possiamo anche specificare un blocco di codice eseguito quando
la condizione dell’if è falsa:

if condizione:
# gruppo di istruzioni eseguite
# se la condizione è vera
else:
# gruppo di istruzioni eseguite
# se la condizione è falsa

In questo caso Python eseguirà il primo blocco se la condizione è vera, oppure il secondo blocco se la condizione
è falsa. Ad esempio:

n = int(input('Inserisci un numero: '))


if n < 0:
print(n, 'è negativo')
else:
print(n, 'è positivo')

In questo caso il programma eseguirà uno dei due print(): il primo se il numero inserito dall’utente è negativo,
il secondo se invece è positivo.

32
È infine possibile aggiungere 1 o più elif, ognuno seguito da una condizione, dai due punti (:) e da un blocco di
codice indentato che viene eseguito solo se la condizione è vera. È anche possibile aggiungere un singolo else
alla fine che viene eseguito se tutte le condizioni precedenti sono false:

if condizione1:
# gruppo di istruzioni eseguite
# se la condizione1 è vera
elif condizione2:
# gruppo di istruzioni eseguite
# se la condizione2 è vera
elif condizioneN:
# gruppo di istruzioni eseguite
# se la condizioneN è vera
else:
# gruppo di istruzioni eseguite
# se tutte le condizioni sono false

Si noti che solo uno di questi blocchi viene eseguito:


▪ se una delle condizioni è vera, il blocco corrispondente viene eseguito;
▪ se invece tutte le condizioni sono false e un else è presente, solo il blocco dell’else viene eseguito.

Nel caso ci siano più condizioni vere, verrà eseguito solo il blocco corrispondente alla prima condizione vera.

Vediamo un esempio:

n = int(input('Inserisci un numero: '))


if n < 0:
print(n, 'è negativo')
elif n > 0:
print(n, 'è positivo')
else:
print(n, 'è zero')

L’esempio usa if ed elif per verificare rispettivamente se il numero inserito dall’utente è negativo o positivo.

Se entrambe le condizioni sono false (cioè quando il numero è uguale a 0), l’else viene eseguito.

9.2 INDENTAZIONE NELL’ISTRUZIONI IF

Nei due esempi che seguono, vedremo che codice apparentemente simile ha significati diversi a seconda
dell’indentazione.

In questo primo esempio, l’else ha lo stesso livello di indentazione del secondo if, e viene quindi eseguito
quando cond1 è vera e cond2 è falsa:

if cond1:
print('cond1 è vera')
if cond2:
print('cond1 è vera, cond2 è vera')
else:
print('cond1 è vera, cond2 è falsa')

33
In quest’altro esempio, l’else ha lo stesso livello di indentazione del primo if, e viene quindi eseguito quando
cond1 è falsa:

if cond1:
print('cond1 è vera')
if cond2:
print('cond1 è vera, cond2 è vera')
else:
print('cond1 è falsa')

Possiamo notare che il blocco di codice indentato sotto l’else viene eseguito quando la condizione dell’if
corrispondente (cioè quello con lo stesso livello di indentazione dell’else) è falsa.

Nel seguente esempio, vediamo come sia possibile usare più if-else annidati per ottenere lo stesso risultato
di un if-elif-else:

n = int(input('Inserisci un numero: '))


if n == 0:
# se il numero è zero
print(n, 'è zero')
else:
# se il numero non è zero
if n > 0:
print(n, 'è positivo')
else:
print(n, 'è negativo')

Possiamo notare che:


▪ il primo print() è indentato sotto l’if, e quindi viene eseguito solo se la condizione n == 0 è vera;
▪ il primo else ha lo stesso livello di indentazione del primo if, quindi viene eseguito solo se la condizione n
== 0 non è vera;
▪ indentato sotto il primo else c’è un blocco di codice di 4 righe, che include un altro if-else;
▪ il secondo print() ha 2 livelli di indentazione, quindi viene eseguito solo quando la prima condizione (n ==
0) è falsa e la seconda (n > 0) è vera;
▪ il secondo else ha lo stesso livello di indentazione del secondo if, quindi viene eseguito solo se la condizione
n > 0 non è vera;
▪ il terzo e ultimo print() ha 2 livelli di indentazione, quindi viene eseguito solo quando la prima (n == 0) e la
seconda (n > 0) condizione sono false.

9.3 SOSTITUIRE LO “SWITCH-CASE”

Un altro costrutto condizionale presente in diversi altri linguaggi è lo switch-case.

Lo switch-case consente di specificare una variabile, seguita da diversi casi che vengono eseguiti in base al valore
della variabile.

Vediamo come implementare questo costrutto in Python.

34
Il seguente esempio mostra parte di un programma in C che in base al valore della variabile n, esegue diversi
blocchi di codice:

// esempio in C
switch (n) {
case 0:
printf('zero\n');
break;
case 1:
case 2:
printf('uno o due\n');
break;
case 3:
printf('tre\n');
break;
default:
printf('numero diverso da 0, 1, 2, 3\n');
break;
}

Questo programma C stampa zero se il valore di n è 0, uno o due se il valore è 1 o 2, tre se il valore è 3, altrimenti
stampa numero diverso da 0, 1, 2, 3.

In Python non esiste il costrutto switch-case, ma è tuttavia possibile ottenere lo stesso risultato semplicemente
usando un if-elif-else:

# esempio in Python
if n == 0:
print('zero')
elif n == 1 or n == 2:
print('uno o due')
elif n == 3:
print('tre')
else:
print('numero diverso da 0, 1, 2, 3')

35
10 CICLI: WHILE E FOR
In Python esistono due tipi di cicli (anche detti iterazioni):
▪ il ciclo while che itera fintanto che una condizione è vera;
▪ il ciclo for che esegue un’iterazione per ogni elemento di un oggetto iterabile.

10.1 CICLO WHILE

Il ciclo while itera fintanto che una condizione è vera:

c = 1
while c<5:
print(c)
c=c+1

Possiamo notare che:


▪ il ciclo while è introdotto dalla keyword while, seguita da una condizione (c<5) e dai due punti (:);
▪ dopo i due punti è presente un blocco di codice indentato (che può anche essere formato da più righe);
▪ il ciclo while esegue il blocco di codice fintanto che la condizione è vera;
▪ in questo caso stampa i numeri da 1 a 4;
▪ quando c diventa 5, la condizione diventa falsa e il ciclo termina.

10.2 CICLO FOR

Il ciclo for ci permette di iterare su tutti gli elementi di un “oggetto iterabile” ed eseguire un determinato blocco
di codice. Un iterabile è un qualsiasi oggetto in grado di restituire tutti gli elementi uno dopo l’altro, come ad
esempio stringhe, liste, tuple, ecc.

# stampa ogni carattere di una stringa


s = "prova"
for c in s:
print(c)

Possiamo notare che:


▪ il ciclo for è introdotto dalla keyword for, seguita da una variabile, dalla keyword in, da un oggetto iterabile
(in questo caso una stringa), e infine dai due punti (:);
▪ dopo i due punti è presente un blocco di codice indentato (che può anche essere formato da più righe);
▪ il ciclo for itera su tutti gli elementi (caratteri) della stringa, li assegna alla variabile c ed esegue il blocco di
codice;
▪ in questo esempio la variabile c assumerà i valori di "p", "r" e così via, che verranno man mano stampati;
▪ una volta che il blocco di codice è stato eseguito per tutti i valori, il ciclo for termina.

Chi ha familiarità con altri linguaggi avrà notato che in Python il ciclo for non usa indici che vengono incrementati
manualmente (come ad esempio avviene in C).

36
10.3 RANGE

Dato che spesso accade di voler lavorare su sequenze di numeri, Python fornisce una funzione chiamata range
che permette di specificare uno valore iniziale o start (incluso), un valore finale o stop (escluso), e uno step, e che
ritorna una sequenza di numeri interi:
▪ range(n) crea una elenco di numeri interi da 0 a n-1 (n è escluso)
▪ range(start,stop) crea un elenco di numeri interi da start a stop-1
▪ range(start,stop,step) crea un elenco di numeri interi da start a stop-1 con passo uguale a step

Vedamo degli esempi:

range(10) # produce 0, 1, 2, …, 9
range(2,7) # produce 2, 3, 4, 5, 6
range(2,10,2) # produce 2, 4, 6, 8 (il 10 no!!!)

Questa funzione è particolarmente utile se combinata con il ciclo for:

for n in range(1, 6):


print('Il quadrato di', n, 'è', n**2)

In questo caso si ottiene un comportamento più simile al for “tradizionale” (come quello di C).

Vediamo come utilizzare range per stampare ogni singolo carattere di una stringa.

# stampa ogni carattere di una stringa


s = "prova"
for i in range(len(s)): # numeri da 0 a len-1
print(s[i])

10.4 BREAK E CONTINUE

Python prevede 2 costrutti che possono essere usati nei cicli for e while:
▪ break interrompe il ciclo;
▪ continue interrompe il passo corrente dell’iterazione e procede al successivo passo.

Ad esempio, possiamo usare un ciclo for per cercare un carattere in una lista e interrompere la ricerca appena
l’elemento viene trovato:

# cerco la lettera o
s = 'prova'
for c in s:
print('Sto controllando', c)
if c == 'o':
print('Elemento trovato!')
break # carattere o trovato, interrompi il ciclo

Non appena il ciclo raggiunge il carattere 'o', la condizione dell’if diventa vera e il break interrompe il ciclo
for. I successivi caratteri 'v' e 'a' non vengono controllati.

37
Vediamo un esempio di utilizzo di continue:

# non stampo le lettere o e a


s = 'prova'
for c in s:
if c == 'o' or c == 'a':
continue # procedi all'elemento successivo
print(c)

In questo esempio, invece, usiamo continue per “saltare” i caratteri 'o' e 'a'. La condizione dell’if è vera per 'o'
e 'a', e in questi casi l’iterazione procede immediatamente con l’elemento successivo senza eseguire il print.
Nel caso di 'p', 'r' e 'v' il continue non viene eseguito e il carattere viene stampato.

10.5 FOR-ELSE E WHILE-ELSE

Una peculiarità di Python è la possibilità di aggiungere un else al for e al while. Il blocco di codice nell’else
viene eseguito se il ciclo termina tutte le iterazioni.

Se invece il ciclo è interrotto da un break, l’else non viene eseguito.

La sintassi è simile a quella che abbiamo già visto con l’if: l’else deve essere indentato allo stesso livello del
for/while, deve essere seguito dai due punti (:) e da un blocco indentato.

Vediamo un esempio dove diamo all’utente 3 tentativi per indovinare un numero:

n = 8
for x in range(3):
guess = int(input('Inserisci un numero da 1 a 10: '))
if guess == n:
print('Hai indovinato!')
break # numero indovinato, interrompi il ciclo
else:
print('Tentativi finiti. Non hai indovinato')

Da notare che anche se l’else segue l’if, l’indentazione corrisponde a quella del for: si tratta quindi di un for-
else, non di un if-else.

Nota: il linguaggio Python non prevede il ciclo di tipo do-while.

38
11 LE STRUTTURE DATI
In molti problemi si ha la necessità di aggregare molti dati di tipo semplice: una struttura dati è un insieme di dati
raggruppati e organizzati secondo uno schema ben definito.

Le strutture dati del linguaggio Python sono le stringhe (già viste), le liste, le tuple, gli insiemi e i dizionari; tali
strutture sono oggetti per le quali, oltre al modo in cui sono organizzati i dati, vengono definiti metodi e
operazioni ammissibili.

STRINGHE (classe str)


Consiste in una sequenza di elementi dello stesso tipo (caratteri) delimitata da singoli o doppi apici. Una stringa
non è modificabile e si può accedere a ogni elemento tramite un indice che ne precisa la posizione nella stringa.

LISTE (classe list) e TUPLE (classe tuple)


Sono elenchi ordinati di elementi accessibili mediante indici che ne identificano la posizione. Gli elementi che
compongono liste e tuple possono essere dello stesso tipo o di tipo diverso ma, in ogni caso, il posizionamento
di un elemento nell’elenco è significativo, ad esempio la tupla (1,2,3) differisce la dalla tupla (1,3,2).

Liste e tuple ammettono la presenza di elementi duplicati ma differiscono per il fatto che le liste sono modificabili
mentre le tuple non lo sono: in una lista si possono aggiungere, togliere o modificare elementi, in una tupla no.

INSIEMI (classe set)


Sono oggetti modificabili, composti da elementi di qualsiasi tipo purchè differenti tra loro (in un insieme non ci
possono essere elementi duplicati). Inoltre un insieme è privo di ordinamento: gli insiemi {1,2,3} e {2,3,1}
sono uguali. Non è possibile accedere ai singoli elementi di un insieme se non elencandoli o estraendoli
dall’insieme.

DIZIONARI (classe dict)


I dizionari sono collezioni non ordinate di coppie del tipo chiave:valore. Si accede a un elemento del
dizionario tramite la chiave per conoscere per conoscere il valore a essa associato.

Un dizionario è modificabile, non ci possono essere elementi duplicati ed è privo di ordinamento.

La seguente tabella mette a confronto le strutture dati del linguaggio Python:

OGGETTO MODIFICABILE ACCESSO ORDINATO DUPLICATI

String NO In base alla posizione SI SI

Lista SI In base alla posizione SI SI

Tupla NO In base alla posizione SI SI

Insieme SI Elencazione, estrazione NO NO

Dizionario SI In base al valore della chiave NO NO

39
11.1 LE LISTE

Una lista si rappresenta elencando gli elementi, che la compongono in sequenza, separati da una virgola. La
sequenza è racchiusa in una coppia di parentesi quadre.

La lista è un insieme di elementi dello stesso tipo o di tipo diverso.

Con una lista si possono, quindi, indicare tanti dati con un solo nome di variabile; gli elementi si distinguono uno
dall’altro attraverso l’indice che ne indica la posizione e che viene posto accanto al nome della lista, tra parentesi
quadre.

Esempi:

anni = [2000, 2004, 2008, 2012, 2016, 2020, 2024, 2028]


frutta = ['mela', 'pera', 'arancia', 'uva']
dati = [37, 52.5, 'camicia']

Le liste anni e frutta sono liste con dati dello stesso tipo, mentre la lista dati contiene dati di tipo diverso.

L’accesso ai singoli elementi di una lista e la definizione di sottoliste avvengono con la stessa modalità con le quali
si estraggono sottostringhe da una stringa (slicing).

Vediamo degli esempi:

>>> anni[3:]
[2012, 2016, 2020, 2024, 2028]
>>> anni[:3]
[2000, 2004, 2008]
>>> frutta[0]
'mela'
>>> frutta[-1]
'uva'
>>> frutta[4]
IndexError: list index out of range

Un indice non valido produce un messaggio di errore.

L’indice di una lista per essere valido deve essere compreso tra 0 e len(lista)-1 oppure se si usano indici negativi
tra –len(lista) e -1).

Il numero di elementi che compongono una lista si ottiene con la funzione len(lista), ad esempio:

>>> len(anni) # restituisce 8


>>> len(frutta) # restituisce 4
>>> len(dati) # restituisce 3

40
Per elencare gli elementi di una lista si usa un ciclo for dove l’indice viene fatto variare entro i limiti desiderati
con la funzione range.

In generale l’accesso agli elementi di una lista può avvenire in due modi:

for indice in range(len(lista)):


...

for elemento in lista:


...

11.2 CREAZIONE DI UNA LISTA

Una lista può essere creata in diversi modi; in particolare la funzione list() trasforma in liste oggetti di altre
classi (stringhe, tuple, …) oppure i dati generati dalla funzione range().

Vediamo degli esempi:

>>> l1 = [] # creazione di una lista vuota


>>> l2 = 3 * [0] # creazione lista con elementi identici [0, 0, 0]
>>> l3 = [12, 35, 99]
>>> l1 = l2 + l3 # concatenazione di liste [0, 0, 0, 12, 35, 99]
>>> l4 = list(range(1,5)) # si ottiene la lista [1, 2, 3, 4]
>>> s = 'python'
>>> l5 = list(s) # si ottiene la lista ['p', 'y', 't', 'h', 'o', 'n']

Nota: la stringa s e la lista l5 contengono gli stessi elementi ai quali si accede allo stesso modo; la differenza sta
nel fatto che la lista è modificabile mentre la stringa no.

11.3 MODIFICA DI UNA LISTA

A ogni elemento di una lista può essere assegnato un nuovo valore con l’istruzione lista[pos]=val.

Per inserire nuovi valori in una lista si usa il metodo append(val) per aggiungere in coda alla lista un elemento
di valore val oppure il metodo insert(pos,val) per inserire il nuovo elemento nella posizione pos.

Infine, per togliere un elemento da una lista si usa il metodo pop(pos) che estrae l’elemento in posizione pos
(se non si specifica la posizione il metodo pop() estrae l’ultimo elemento della lista).

Il metodo pop() non si limita ad eliminare un elemento dalla lista ma ne restituisce il contenuto che può essere
memorizzato in una variabile.

>>> l = [12, 35, 99, 4, 21]


>>> l[0] = 80 # la lista diventa [80, 35, 99, 4, 21]
>>> l.append(10) # la lista diventa [80, 35, 99, 4, 21, 10]
>>> l.insert(2,5) # la lista diventa [80, 35, 5, 99, 4, 21, 10]
>>> a=l.pop(5) # la lista diventa [80, 35, 5, 99, 4, 10]
# il valore 21 viene passato alla variabile a

Nota: nel linguaggio Python non è previsto l’array che indica una struttura dati di tipo omogeneo ma possono
essere utilizzate le liste con le quali implementare vettori e matrici.
41
11.4 RIMUOVERE UN ELEMENTO DA UNA LISTA

Oltre al metodo pop() è possibile utilizzare altre istruzioni per rimuovere un elemento da una lista (senza però
restituirne il contenuto).

Possiamo usare il metodo remove(val) per eliminare un elemento di valore val (viene eliminato il primo
trovato nella lista) oppure la funzione del() specificando l’elemento da eliminare.

>>> l = [12, 35, 99, 35, 21]


>>> l.remove(35) # la lista diventa [12, 99, 35, 21]
>>> del(l[1]) # la lista diventa [12, 35, 21]

11.5 ULTERIORI FUNZIONI E METODI

Esistono ulteriori funzioni e metodi che possono essere utilizzati con le liste.

FUNZIONE DESCRIZIONE

min() e max() per trovare l’elemento più piccolo/grande (se gli elementi sono comparabili)

sum() restituisce la somma degli elementi (numerici) della lista

METODO DESCRIZIONE

sort() ordina gli elementi della lista dal più piccolo al più grande

reverse() inverte l’ordine degli elementi della lista

extend(seq) estende la lista aggiungendo alla fine gli elementi di seq

copy() crea e restituisce una copia della lista

clear() rimuove tutti gli elementi della lista

count(val) conta quante volte un elemento è presente nella lista

index(val) restituisce l’indice di un elemento (il primo trovato) – errore se non presente

index(val,pos) restituisce l’indice di un elemento a partire dalla posizione pos

Alcuni dei metodi visti (pop, index) danno errore se la posizione specificata o l’elemento cercato non esistono. È
necessario quindi effettuare un test di controllo prima di eseguire il metodo, ad esempio:

>>> l = [1,2,3,4]
>>> l.index(5) # errore perché il valore 5 non è presente nella lista
ValueError: 5 is not in list

>>> if 5 in l:
l.index(5) # effettuo un controllo prima

42
11.6 ARRAY CON LE LISTE (VETTORI E MATRICI)

È possibile implementare un vettore in Python utilizzando una lista contenente valori dello stesso tipo.

Una lista può avere come elementi altre liste; è possibile implementare una matrice utilizzando liste che hanno
per elementi liste con lo stesso numero di elementi tutti dello stesso tipo.

Ad esempio, la lista mat:

>>> mat = [[1,2,3] , [4,5,6] , [7,8,9] , [10,11,12]]

rappresenta un array a due dimensioni, cioè una matrice, composta da 4 righe e 3 colonne.

Per accedere a un elemento della matrice mat si usa la forma mat[r][c] dove il primo indice r indica la riga
e il secondo indice c indica la colonna.

11.7 LE TUPLE

Le tuple sono collezioni di dati simili alle liste; differiscono da queste perché le tuple sono immutabili mentre le
liste sono mutabili.

Una tupla si rappresenta elencando gli elementi che la compongono, in sequenza e separati da una virgola. La
sequenza è racchiusa in una coppia di parentesi tonde.

Le tuple sono adatte per rappresentare dati che non cambiano mai; inoltre l’accesso ad dati di una tupla è più
veloce rispetto alle liste.

Esempi:

>>> nascita = (25, 'marzo', 1995)


>>> giorni = ('Lun', 'Mar', 'Mer', 'Gio', 'Ven', 'Sab', 'Dom')
>>> colori = ('rosso', 'giallo', 'verde')

Una tupla può essere creata in molti modi; ad esempio, è possibile utilizzare la funzione tuple() che trasforma
in tupla i dati generati dalla funzione range() oppure i dati di una lista.

Con le tuple si possono utilizzare tutti le operazioni permesse con le liste, ad eccezione di quelle che le
modificano.

Esempi:

>>> tupla = (1,2,3,4) # crea una tupla


>>> sum(tupla) # restituisce 10 cioè la somma degli elementi
>>> len(tupla) # restituisce la lunghezza della tupla (4)
>>> tupla.remove(0) # errore – una tupla è immutabile
AttributeError: 'tuple' object has no attribute 'remove'

43
11.8 GLI INSIEMI

Un insieme è un contenitore di dati con le stesse caratteristiche degli insiemi della matematica: in un insieme
non ci sono elementi duplicati e gli elementi dell’insieme non sono ordinati (cioè non sono in sequenza).

In Python, un insieme si indica racchiudendo gli elementi che le compongono tra parentesi graffe, separati da
una virgola.

La funzione set() definisce l’insieme vuoto oppure un insieme creato partendo dagli elementi di altre strutture
quali stringhe, liste e tuple.

Esempi:

>>> vuoto = {}
>>> vocali = {'a', 'e', 'i', 'o', 'u'}
>>> vocali = set("aeiou")

In un insieme non ci sono duplicati e gli elementi non sono ordinati.

>>> set("banana")
{'n', 'b', 'a'}
>>> {'a', 'n', 'b'} == {'n', 'b', 'a'}
True

Volendo ottenere una lista o una tupla senza duplicati basta trasformarla in un insieme e poi di nuovo in una lista.

>>> lista = [1, 2, 3, 3, 4, 4]


>>> insieme = set(lista)
{1, 2, 3, 4}
>>> lista = list(insieme)
[1, 2, 3, 4]

Gli elementi di un insieme non sono accessibili tramite un indice; si può controllare se un elemento appartiene
ad un insieme con gli operatori in e not in.

Per sapere quanti sono gli elementi di un insieme si usa la funzione len().

11.9 I METODI DEGLI INSIEMI

METODO DESCRIZIONE

add(val) aggiunge un elemento all’insieme

pop() estrae un elemento (a caso) dall’insieme

remove(val) rimuove l’elemento val dall’insieme – errore se non presente

discard(val) rimuove l’elemento val dall’insieme – non dà errore se non presente

clear() svuota l’insieme

Nota: Possono essere utilizzati anche i metodi min, max e sum.


44
11.10 LE OPERAZIONI INSIEMISTICHE

È possibile eseguire le operazioni insiemistiche di unione, intersezione e differenza e si può controllare se un


insieme è un sottoinsieme di un altro.

>>> s1.union(s2) # unione


>>> s1.intersection(s2) # intersezione
>>> s1.difference(s2) # differenza
>>> s1.issubset(s2) # True se s1 è sottoinsieme di s2

11.11 I DIZIONARI

Un dizionario è una collezioni di coppie chiave:valore che associano a una chiave il valore corrispondente.

L’accesso ai dati avviene in modo associativo cioè specificando il valore di una chiave per ottenere il valore
associato.

Un dizionario si costruisce elencando le coppie chiave:valore tra parentesi graffe separandole con la virgola.

Esempi:

>>> vuoto = {}
>>> vuoto = dict() # creano un dizionario vuoto

>>> nazioni_capitali = {'italia':'roma','francia':'parigi','spagna':'madrid'}

>>> nazioni_capitali['francia']
'parigi'

Un dizionario è un oggetto modificabile: possono essere aggiunti nuovi elementi e quelli esistenti possono essere
rimossi o modificati.

Per inserire o modificare un elemento si utilizza la sintassi dizionario[chiave]=valore.

Per eliminare un elemento si può usare il metodo pop() o la funzione del(). In entrambi i casi se l’elemento
non è presente viene generato un errore. La presenza di un elemento chiave si controlla con gli operatori in e
not in.

Per esaminare l’intero dizionario si un ciclo for:

for chiave in dizionario: istruzioni

Il metodo keys() dei dizionari produce una lista con l’elenco delle chiavi:

>>> persona = {'nome':'Mario', 'cognome':'Rossi', 'anni':40}


>>> persona.keys()
dict_keys(['nome', 'cognome', 'anni'])

45
Per controllare che un dizionario non sia vuoto ed evitare errori nell’accesso si usa la funzione len() che
restituisce il numero di elementi presenti. Il metodo clear() svuota un dizionario.

11.12 ACCESSO AI DATI DI UN DIZIONARIO

Ci sono diversi metodi per accedere ai dati di un dizionario.

Consideriamo il seguente dizionario:

crediti = {'Gianni':225, 'Ugo':300, 'Laura':180, 'Franco':123}

Vediamo alcuni esempi:

for nome in crediti:


print(nome, crediti[nome])

Gianni 225
Ugo 300
Laura 180
Franco 123

for importo in crediti.values():


print(importo, end=' ')

225 300 180 123

for dati in crediti.items():


print(dati)

('Gianni', 225)
('Ugo', 300)
('Laura', 180)
('Franco', 123)

for nome,importo in crediti.items():


print(nome, importo)

Gianni 225
Ugo 300
Laura 180
Franco 123

46
12 LE FUNZIONI
Con il termine funzione si intende un procedimento che riceve valori come argomenti in ingressi e restituisce un
valore come risultato.

La sintassi generale di una funzione è la seguente:

def nome_funzione(parametri):
istruzioni
...

return valore

La parola def indica l’inizio della definizione di una funzione.

Dopo il nome della funzione, le parentesi tonde servono a contenere l’elenco dei parametri, separati da virgola,
che saranno posi associati agli oggetti passati alla funzione dal programma chiamante.

Le istruzioni che formano il corpo della funzione sono scritte in modo indentato sotto la prima riga e
rappresentano il codice che viene eseguito alla chiamata della funzione.

12.1 LA CHIAMATA DELLA FUNZIONE

Per effettuare la chiamata di una funzione da un qualunque punto del programma, dopo averla definita, occorre
specificare il nome della funzione seguito dall’elenco, tra parentesi tonde, degli argomenti da passare ai
parametri della funzione.

nome_funzione(argomenti)

12.2 I VALORI RESTITUITI

Una funzione può restituire un valore tramite l’istruzione return seguita da un valore o da una variabile. Questa
istruzione provoca il ritorno del controllo al programma chiamante.

Esempio:

def somma(a, b):


s = a + b
return s

totale = somma(10, 20)


print(totale)

La funzione somma deve essere definita prima dell’inizio del programma principale.

I valori 10 e 20 vengono passati alla funzione rispettivamente ai parametri a e b.

La funzione calcola il risultato e restituisce il valore al programma chiamante che lo memorizza nella variabile
totale per poi stamparne il contenuto.

47
12.3 PARAMETRI FORMALI E ATTUALI

Le variabili indicate, tra parentesi tonde, nella definizione della funzione si chiamano parametri formali.

Invece le variabili che sono gli argomenti nella chiamata della funzione si chiamano parametri attuali.

Nell’uso delle funzioni occorre rispettare le seguenti tre regole:


▪ corrispondenza di tipo: il tipo del parametro formale e attuale devono corrispondere;
▪ corrispondenza di numero: il numero degli argomenti deve corrispondere al numero dei parametri;
▪ corrispondenza di posizione: il primo argomento viene associato al primo parametro e così via.

12.4 IL PASSAGGIO DEGLI ARGOMENTI AI PARAMETRI

Indica l’operazione con la quale il programma chiamante invia gli oggetti alla funzione, assegnandoli ai nomi dei
parametri.

Se l’oggetto passato è immutabile (numero, stringa, tupla), il suo valore non cambia durante l’esecuzione della
funzione (passaggio per valore).

Se invece l’oggetto passato è mutabile (ad esempio una lista), gli eventuali cambiamenti di valore dei parametri,
durante l’esecuzione della funzione, influenzano i valori degli oggetti che il programma chiamante ha passato alla
funzione.

12.5 VARIABILI GLOBALI E LOCALI

Le variabili definite nel programma principale e quindi al di fuori di tutte le funzioni sono chiamate variabili globali
in quanto possono essere utilizzate all’interno di ogni funzione.

Invece le variabili definite all’interno delle funzioni sono chiamate variabili locali e possono essere utilizzate
esclusivamente all’interno della funzione in cui sono state definite.

Esempio:

# variabile globale
a=7

# definizione della funzione


def stampa():
b = 5
print(b) # 5
print(a) # 7

# programma principale
stampa() # visualizza 5 e 7
print(a) # visualizza 7
print(b) # errore: name 'b' is not defined

Quando viene chiamata la funzione stampa() vengono visualizzati i valori 5 (variabile locale b) e 7 (variabile
globale a). Successivamente, all’interno del programma principale, la prima istruzione print(a) visualizza 7
(variabile globale a) mentre la seconda dà errore in quanto la variabile b non è stata definita nel programma
principale ma all’interno della funzione.
48
Una funzione non è in grado di modificare il valore di una variabile globale.

Vediamo un esempio:

# variabile globale
x = 10.32

# definizione della funzione


def f():
x = 10
print(x) # 10

# programma principale
print(x) # visualizza 10.32
f() # visualizza 10
print(x) # visualizza 10.32

L’assegnazione x=10 all’interno della funzione f() ha semplicemente creato una nuova variabile locale x (che
verrà poi distrutta all’uscita della funzione).

Le limitazioni viste in precedenza possono essere superate con la parola chiave global.

Esempio:

# variabile globale
x = 20.1

# definizione funzioni
def f1():
global x
x = 10
print(x) # 10

def f2():
global y
y = 3 # 3

# programma principale
print(x) # visualizza 20.1
f1() # visualizza 10
print(x) # visualizza 10 – f1 ha modificato il valore di x
f2() # visualizza 3
print(y) # visualizza 3 - il programma principale vede y dichiarata in f2

12.6 I MODULI

Un modulo è un file cono estensione .py e contenente definizioni di funzioni, istruzioni e costanti.

Sono utilizzati per:


▪ suddividere un programma complesso in diversi file per facilitarne il controllo e la manutenzione;
▪ salvare all’interno di un file una o più funzioni che possono essere utili in programmi diversi, senza la necessità
di copiare ogni volta la loro definizione nel codice del programma.

49
Il contenuto di un modulo diventa disponibile in un programma tramite l’istruzione import.

import nome_modulo

Dopo l’importazione le funzioni e gli oggetti definiti nel modulo sono richiamabili nel programma con la notazione
con il punto:

nome_modulo.nome_funzione()
nome_modulo.oggetto

Un modulo può essere importato anche con altre modalità:

import nome_modulo as alias

In questo modo è possibile utilizzare funzioni e oggetti scrivendo: alias.funzione() o alias.oggetto

from nome_modulo import *

In questo caso vengono importate tutte le risorse (funzioni e oggetti) del modulo e per richiamarle non è
necessario utilizzare la notazione con il punto.

Esempi:

import modulo1

modulo1.totale=10
modulo1.stampa()

import modulo1 as m1

m1.totale=10
m1.stampa()

from modulo1 import *

totale=10
stampa()

12.7 I MODULI PREDEFINITI

Oltre ai moduli definiti dal programmatore, è possibile usare i moduli predefiniti (ad esempio i moduli math,
random, …) del linguaggio Python che appartengono alla libreria standard di Python e che comprende funzioni,
tipi e costanti di uso comune utili nella programmazione.

50
13 LA GESTIONE DELLE ECCEZIONI
Se durante l'esecuzione di un programma un comando fa qualcosa di non consentito (ad esempio: dividere per
zero, usare un indice inesistente in una lista o chiamare una funzione con un numero errato di argomenti) Python
blocca immediatamente l'esecuzione, esce dal programma e ci segnala l'errore (errore di runtime).

Il linguaggio Python prevede la gestione delle eccezioni che consente di intercettare le situazioni nelle quali si
creano errori che interrompono la normale esecuzione del programma.

Ciò permette di inviare messaggi di errore e/o avvertimenti all’utente senza bloccare improvvisamente
l’esecuzione cosa che sarebbe piuttosto imbarazzante in un programma "serio".

Vediamo un esempio:

nomi = ["Piero", "Mario", "Carlo", "Luigi"]


n = int(input("Ho pensato quattro nomi. Quale vuoi sapere? "))
print(nomi[n])

Quando lanciamo questo programma possiamo provocare un ValueError digitando "xyz" al prompt (Python
deve tradurre la nostra stringa in un intero, ma la stringa non ha significato); oppure possiamo provocare un
IndexError digitando "10" (nell'istruzione successiva chiediamo a Python di leggere il decimo elemento di
una lista con solo quattro elementi).

In entrambi i casi l’esecuzione del programma termina con la visualizzazione dell’errore commesso (il programma
ha generato un’eccezione).

13.1 L’ISTRUZIONE TRY … EXCEPT

La gestione strutturata delle eccezioni si ottiene racchiudendo gruppi di istruzioni che potrebbero generare errori
durante l’esecuzione e specificando le attività da svolgere quando una eccezione viene intercettata.

Per questo scopo si utilizza l’istruzione try … except che ha la seguente sintassi:

try:
istruzioni
...
except:
istruzioni
...

Le istruzioni try ed except devono essere allo stesso livello di indentazione e devono essere entrambe seguite
da un blocco di codice indentato:
▪ Python tenta dapprima di eseguire il blocco try;
▪ se in esso si verifica un errore, salta immediatamente (senza terminarlo) al blocco except, che esegue per
intero;
▪ se invece non si verificano errori l'except viene saltato.

In ogni caso, dopo aver eseguito il try o l'except il programma continua con la prima istruzione successiva nel
programma.

51
Vediamo come utilizzare l’istruzione nell’esempio visto precedente:

nomi = ["Piero", "Mario", "Carlo", "Luigi"]


try:
n = int(input("Ho pensato quattro nomi. Quale vuoi sapere? "))
print(nomi[n])
except:
print("Input non valido")

Se si prova a scrivere al prompt qualcosa che non ha significato, il programma non bloccherà più il programma
segnalando un errore, ma scriverà "Input non valido".

E se volessimo far ripetere l'input fino a quando otteniamo il risultato voluto?

nomi = ["Piero", "Mario", "Carlo", "Luigi"]


while True:
try:
n = int(input("Ho pensato quattro nomi. Quale vuoi sapere? "))
print(nomi[n])
break
except:
print("Input non valido")

L’istruzione try ... except è ora inserita all'interno di un ciclo while infinito:
▪ se nel try si verifica un errore il programma salterà all'except, avvisando dell'input scorretto e ripetendo il
ciclo while;
▪ se invece tutto va bene viene eseguito il break alla fine del try e si esce dal ciclo continuando il programma.

13.2 GESTIONE DI SPECIFICHE ECCEZIONI

L'istruzione except può essere seguita dal nome di una o più eccezioni (ad esempio: NameError,
TyperError, ValueError, ...) separati da virgole (attenzione alla corrispondenza tra maiuscole e
minuscole).

In questo caso essa intercetta solo quel tipo di eccezioni, mentre le altre non vengono gestite.

Dopo una try ci possono essere più except in modo tale da gestire diversamente errori diversi.

Vediamo un esempio:

nomi = ["Piero", "Mario", "Carlo", "Luigi"]


while True:
try:
n = int(input("Ho pensato quattro nomi. Quale vuoi sapere? "))
print(nomi[n])
break
except ValueError: # se abbiamo introdotto una stringa senza senso
print("Devi introdurre un numero!")
except IndexError: # se abbiamo introdotto un indice non valido
print("Hai introdotto un indice non valido!")
except:
print("Errore imprevisto!")

52
L’istruzione try ... except dovrebbe essere usata solo per gestire delle eccezioni che il programmatore ha
previsto.

Nell’esempio precedente è stato utilizzata anche una except senza specificare il tipo di errore che consente di
"catturare" anche eccezioni non previste e che, probabilmente, derivano da nostri errori di programmazione.

Probabilmente l'ultimo except non verrà mai eseguito: nel caso lo fosse dovremmo eseguire il programma con
il debugger per capire quale tipo di errore sia capitato (e gestirlo di conseguenza).

13.3 TIPI DI ERRORE

I tipi di errore più comuni che si possono utilizzare con except sono i segenti:

ERRORE DESCRIZIONE

ValueError Valore della variabile non corretto

NameError Nome della variabile sconosciuto

ZeroDivisionError Divisione per zero

TypeError Operazione non valida per quel tipo di dato

Questi tipi sono organizzati in una gerarchia (https://docs.python.org/3/library/exceptions.html#exception-


hierarchy), che include eccezioni più o meno specifiche che vengono utilizzate per situazioni diverse.

Per esempio, l’eccezione ZeroDivisionError è un caso particolare di ArithmeticError, che è un


sotto-tipo di Exception, che a sua volta è un sotto-tipo di BaseException.

È possibile aggiungere dopo l’except, la keyword as seguita dal nome di una variabile (ad esempio err).

Questo rende accessibile l’errore all’interno del blocco di codice dell’except permettendoci, tra le altre cose,
di stamparlo.

Esempio:

try:
a=10/0 # provoco un errore
except ZeroDivisionError as err:
print(err)

Il programma intercetterà l’errore e visualizzerà la descrizione che Python associa all’errore commesso.

In questo caso verrà visualizzato il messaggio: division by zero.

53
13.4 ELSE

È possibile aggiungere un else dopo l’except che viene chiamato se il codice nel blocco del try viene eseguito
senza che ritorni nessuna eccezione.

Esempio:

try:
n = int(x) # prova a convertire x in intero
except ValueError:
# eseguito in caso di ValueError
print('Numero non valido!')
else:
# eseguito se non ci sono errori
print('Numero valido!')

13.5 FINALLY

Se vogliamo specificare una o più operazioni che vanno eseguite sia in caso di errore che in caso di successo,
possiamo aggiungere un finally seguito dai due punti e da un blocco di codice indentato che verrà sempre
eseguito.

Vediamo un esempio di utilizzo dell’istruzione finally nella gestione dei file (argomento che vedremo
successivamente):

f = open('test.txt', 'r') # apre un file


try:
f.read() # operazione di lettura
except:
print("Errore in fase di lettura")
finally:
f.close() # il file deve essere chiuso in ogni caso:
# se l’operazione di lettura è andata bene oppure no

13.6 LE ECCEZIONI E LE FUNZIONI

Il blocco try ... except gestisce anche le eccezioni che si verificano all'interno delle funzioni che vengono
chiamate nel try.

Esempio:

def divisione():
x=10/0 # viene generato un errore
return x

try:
divisione()
except:
print("Errore")

L’errore presente nella funzione verrà intercettato dal try che contiene la chiamata alla funzione.

54
13.7 L’ISTRUZIONE RAISE

Possiamo infine forzare volontariamente un'eccezione con l'istruzione raise.

La sintassi è: raise nome_eccezione[(parametro)]

Il parametro è opzionale e, se presente, è di solito una stringa che viene scritta subito dopo il nome dell'errore
come spiegazione.

Esempio:

def divisione(a,b):
if b==0:
raise ZeroDivisionError("Stai facendo una divisione per zero")
return a/b

try:
divisione(10,0)
except ZeroDivisionError as err:
print(err)

All’interno della funzione divisione viene controllato se b è uguale a zero.

In questo caso viene forzata l’eccezione ZeroDivisionError utilizzando l’istruzione raise e indicando il
messaggio che verrà visualizzato all’interno della try … except contenente la chiamata alla funzione e che,
quindi, intercetterà l’eccezione.

Il raise è usato spesso all'interno delle funzioni da noi programmate, per segnalare al programma principale
che qualcosa è andato storto: di solito se succede qualcosa di anomalo all'interno di una funzione il
programmatore scrive il raise senza nessun blocco try, così Python genera un errore ed esce
immediatamente dalla funzione.

55
14 I FILE
Finora nei programmi che abbiamo realizzato abbiamo inserito i dati tramite tastiera e li abbiamo memorizzati in
variabili oppure abbiamo mostrato i dati presenti nelle variabili sul monitor: abbiamo cioè trasferito dati
dall’esterno verso la memoria centrale (RAM) e viceversa.

La caratteristica dei dati presenti nella RAM è quella di essere volatili cioè i dati in essa contenuti non sono
memorizzati permanentemente ma si perdono al termine dell’esecuzione del programma.

Nei problemi reali vi è invece la necessità di conservare i dati in archivi permanenti al fine di poterli riutilizzare in
seguito.

14.1 DEFINIZIONE DI ARCHIVIO

“Insieme organizzato di informazioni, inerenti il medesimo argomento, memorizzate in dispositivi in grado di


conservarle nel tempo e organizzate in modo da essere facilmente consultabili.”

Un archivio è un file memorizzato su una memoria di massa (hard disk, chiavetta usb, …) avente un nome e una
estensione che indica il tipo di file e con quale programma lo possiamo gestire (esempi: testo.doc, prova.pdf, …)

È una collezione di record (informazioni logicamente omogenee) che descrivono i singoli elementi della realtà
considerata.

Ogni record è composto da un insieme di campi che contengono i valori assunti dalle proprietà scelte per
descrivere la realtà di interesse.

Esempio: elenco studenti di una classe

Progressivo Matricola Cognome Nome

1 1002 Bianchi Antonio

2 1045 Gialli Elena

3 1023 Neri Giulia

4 1012 Rossi Mario

5 1065 Verdi Filippo

6 1089 Rossi Anna

56
14.2 OPERAZIONI SUI FILE

Le operazioni fondamentali che riguardano il trattamento dei file sono:


▪ apertura del file: si crea un collegamento tra RAM e memoria di massa contenente il file sul quale si vogliono
svolgere operazioni di lettura (input) e scrittura (output);
▪ lettura dal file: operazioni che trasferiscono dati dal file alla memoria centrale;
▪ scrittura sul file: operazioni che trasferiscono dati dalla memoria centrale al file;
▪ chiusura del file: si chiude il collegamento tra la RAM e la memoria di massa che contiene il file (non sono più
possibili operazioni sul file a meno che non si effettui una nuova apertura).

14.3 TIPOLOGIE DI FILE

Esistono due tipologie di file in base al loro contenuto:


▪ file di testo: contengono testo memorizzato su linee ciascuna terminante con il carattere di fine linea; ogni
byte del file rappresenta un carattere codificato in ASCII/UNICODE;
▪ file binari: sono un insieme di bit (sempre organizzati in byte) ma il cui significato è stabilito dal programma
utilizzato per creare il file o per visualizzarne il contenuto.

Esempi di file di testo:


▪ txt, html, csv (il loro contenuto può essere visualizzato con blocco note)

Esempi di file binari:


▪ immagini (jpg, gif, …), pdf, doc, exe (necessitano di appositi programmi per essere visualizzati)

14.4 UTILIZZO DEI FILE DI TESTO IN PYTHON

Un programma che deve utilizzare i dati contenuti in un file prevede le seguenti fasi di lavoro:
▪ apertura del file specificando il nome del file, il tipo di accesso al file e la variabile (di tipo file) alla quale verrà
associato il file;
▪ operazioni di manipolazione del file (lettura e scrittura);
▪ chiusura del file.

Le istruzioni per la gestione di un file di testo in Python sono:

OPERAZIONE METODI O FUNZIONI

Apertura open

Lettura readline - read - readlines

Scrittura write - print

Chiusura close

57
14.5 ACCESSO AI FILE DI TESTO

L’accesso ai file di testo è sempre di tipo sequenziale cioè per trovare un certo dato è sempre necessario scorrere
i record del file, a partire dal primo fino a quello che ci serve, nello stesso ordine con cui sono stati registrati.

Nota: esistono anche file ad accesso diretto nei quali è possibile accedere direttamente ad un record specificando
la sua posizione.

14.6 LETTURA E SCRITTURA DI UN FILE DI TESTO

È possibile aprire un file di testo per eseguire le seguenti operazioni:


▪ scrivere caratteri in un file;
▪ leggere caratteri da un file;
▪ aggiungere caratteri al file in coda a quelli già esistenti (append).

La lettura (di un file già esistente) avviene a partire dal primo record fino al raggiungimento della fine del file.

La scrittura avviene sempre dall’inizio di un file; se il file è già esistente cancella tutti i dati in esso presenti.

Per scrivere su un file già esistente conservandone il precedente contenuto è necessario effettuare l’operazione
di append (aggiunta in coda).

14.7 APERTURA DI UN FILE


variabilefile = open(nomefile, modalità)

▪ nomefile: stringa che contiene il percorso indicante la cartella in cui il file è contenuto (non necessario se il file
si trova nella stessa cartella del programma che abbiamo realizzato in Python) seguito dal nome del nome del
file (completo di estensione);
▪ modalità: stringa che specifica la modalità di apertura del file cioè indica se il file sarà utilizzato per operazioni
di lettura, scrittura o altro;
▪ variabilefile: nome della variabile di tipo file che conterrà il collegamento al file e che verrà utilizzata per tutte
le successive operazioni.

Modalità di apertura

MODALITÀ ESEMPIO NOTE


Apre il file in sola scrittura (se il file non esiste viene creato; se
'r' open(nomefile, 'r')
esiste viene cancellato e ricreato)
Apre il file in sola lettura (se il file non esiste viene generato
'w' open(nomefile, 'w')
un errore)
Apre il file in sola scrittura ma in modalità append (se il file
'a' open(nomefile, 'a')
non esiste lo crea)

58
Esempi:

f = open('prova.txt', 'r')

apre il file prova.txt in sola lettura; il file si deve trovare nella stessa cartella del programma

f = open('C:\\dati\\prova.txt', 'w')

apre il file prova.txt in scrittura; il file viene creato (se non esiste) nella cartella c:\dati

14.8 CHIUSURA DEL FILE

Terminate le operazioni di lettura o scrittura è necessario sempre chiudere il file con il comando: f.close()

14.9 ESEMPIO: CREAZIONE DI UN FILE DI TESTO (METODO WRITE)


f = open('prova.txt', 'w')
f.write('prima riga di dati\n')
f.write('seconda riga di dati\n')

f.close()

Dopo aver aperto il file in modalità scrittura si utilizza il metodo write() per scrivere una riga nel file (al termine
è necessario aggiungere l’invio a capo \n)

Nota: è possibile utilizzare anche l’istruzione print(stringa, file=f)

14.10 ESEMPIO: LETTURA DI UN FILE DI TESTO (METODO READLINE)

La lettura di un file di testo può essere effettuata riga per riga dall’inizio fino a giungere alla fine del file (è
necessario un modo per controllare quando il file termina)

f = open('prova.txt', 'r')
s = f.readline()
while s != '':
s = f.readline()
f.close()

Dopo aver aperto il file in modalità lettura viene effettuato un ciclo finchè non viene letta una riga vuota.

14.11 ESEMPIO: AMPLIAMENTO DI UN FILE DI TESTO (APPEND)

Posso aggiungere dati ad un file di testo già esistente ma solamente in coda.

f = open('prova.txt', 'a')
f.write('nuova riga di dati\n')

f.close() chiudo il file

59
14.12 CARICAMENTO DI UN FILE DI TESTO IN UNA LISTA

A volte nei programmi è utile salvare il contenuto di un file di testo in una lista in modo da poterne facilmente
manipolare il contenuto all’interno del programma (ed eventualmente alla fine risalvare sul file il contenuto della
lista).

Python mette a disposizione due metodi con i quali è possibile trasferire il contenuto del file in una lista:
▪ readlines(): crea una lista a partire dal contenuto del file; ogni riga del file (compreso il carattere di fine
riga) sarà un elemento (stringa) della lista;
▪ read(): crea una stringa contenente tutto il file; per ottenere una lista occorre scomporre la stringa
utilizzando il metodo splitlines(); (con questa modalità non vengono letti i fine riga).

Esempi:

Creo con il blocco note il file Amici.txt contenente in ciascuna riga un nome.

Lettura con il metodo readlines


>>> f = open('Amici.txt','r')
>>> l = f.readlines()
>>> type(l)
<class 'list'>
>>> l
['Mario\n', 'Antonio\n', 'Giuseppe\n', 'Luca\n']
>>> f.close()

Lettura con il metodo read


>>> f = open('C:\\Users\\Fabrizio\\Desktop\\Amici.txt','r')
>>> s = f.read()
>>> s
'Mario\nAntonio\nGiuseppe\nLuca\n'
>>> l = s.splitlines()
>>> l
['Mario', 'Antonio', 'Giuseppe', 'Luca']
>>> f.close()

Scrittura di una lista in un file di testo


È necessario scrivere ogni elemento della lista in una riga terminata dal carattere di fine riga ‘\n’.

Per fare ciò si utilizza un ciclo:

l = ['Mario', 'Antonio', 'Giuseppe', 'Luca']


f = open('prova.txt','w')
for elem in l:
f.write(elem + '\n')
f.close()

60
14.13 COME CONTROLLARE SE UN FILE ESISTE?

Soprattutto prima di leggere un file è necessario controllare se questo esiste altrimenti il programma terminerà
generando un errore. Utilizzando il modulo esterno os si hanno a disposizione, ad esempio, i seguenti metodi:

METODO NOTE

os.path.exists(nomefile) Restituisce True o False se il file esiste o no

os.path.getsize(nomefile) Restituisce la dimensione del file in byte

os.rename(oldfile, newfile) Rinomina il file

os.remove(nomefile) Elimina il file

Esempio:

import os
if not os.path.exists('prova.txt'):
print('Errore: file inesistente')
else:
f = open('prova.txt','r')
...
...
f.close()

14.14 LA GESTIONE DEGLI ERRORI CON I FILE

È bene intercettare eventuali errori imprevisti di tipo IOError quando si lavora con i file:

Esempio:

import os
nomefile="prova.txt"
try:
if os.path.exists(nomefile)==True:
f=open(nomefile, "r")

try:
s=f.readline().rstrip()
while s!="":
print(s)
s=f.readline().rstrip()
except IOError as err:
print(err)
finally:
f.close()

else:
print("Il file non esiste")

except IOError as err:


print(err)

61
14.15 SALVARE STRUTTURE DATI ALL’INTERNO DI FILE (PICKLE)

Salvare una struttura dati all’interno di un file non sempre è un’operazione semplice soprattutto nel caso di
oggetti annidati.

È possibile però utilizzare la libreria pickle che ci semplifica il lavoro. La struttura dati viene “serializzata” e
salvata all’interno di un file binario.

Esempi:

Salvataggio oggetto su file

import pickle

...
...

file = open(nomefile, "wb")


pickle.dump(oggetto, file)
file.close()

Caricamento oggetto da file

import pickle

file = open(nomefile, "rb")


oggetto = pickle.load(file)
file.close()

Nota: rb e wb sono modalità di apertura in lettura e scrittura di un file binario.

62
15 LA PROGRAMMAZIONE AD OGGETTI
Un programma è la traduzione di un algoritmo, cioè del procedimento risolutivo di un certo problema, utilizzando
un apposito linguaggio di programmazione.

Un programma è, quindi, una sequenza di azioni che operano su alcuni dati per risolvere un certo problema.

È possibile scrivere un programma utilizzando diversi stili o paradigmi. I due paradigmi più utilizzati sono la
programmazione imperativa e la programmazione ad oggetti.

15.1 LA PROGRAMMAZIONE IMPERATIVA

La programmazione imperativa (dal latino imperare = comandare) è il più antico paradigma di programmazione.
Secondo questo paradigma, un programma consiste in una sequenza chiaramente definita di istruzioni date a un
computer.

Il codice sorgente dei linguaggi imperativi mette insieme i comandi che determinano cosa deve essere fatto dal
computer per raggiungere il risultato desiderato. I valori utilizzati nelle variabili vengono modificati durante
l’esecuzione del programma.

I vari linguaggi di programmazione imperativi possono a loro volta essere suddivisi in tre ulteriori stili di
programmazione:
▪ strutturata;
▪ procedurale;
▪ modulare.

15.2 LA PROGRAMMAZIONE STRUTTURATA

La programmazione strutturato utilizza strutture di controllo specifiche (sequenza, selezione e iterazione).

Ricordiamo il teorema di Bohm-Jacopini del 1965 che afferma che qualunque algoritmo può essere implementato
in fase di programmazione utilizzando solamente le tre strutture di controllo sopra citate.

15.3 LA PROGRAMMAZIONE PROCEDURALE

La programmazione procedurale divide l’attività che deve essere svolta da un programma in attività secondarie
più piccole (procedure e funzioni), che sono descritte singolarmente nel codice.

Questo paradigma utilizza l’approccio “top-down” in cui il progetto di un sistema complesso viene diviso via via
in problemi più semplici da affrontare identificando dei sottoprogrammi che realizzano le operazioni che il
sistema deve svolgere.

L’intero sistema è quindi concepito come una interazione di procedure e funzioni che operano su strutture dati
comuni.

63
Possiamo illustrare questo tipo di procedimento come nella figura seguente dove esiste un programma principale
con una struttura dati ed un insieme di subroutine le quali vengono chiamate per eseguire delle operazioni su
questi dati.

15.4 LA PROGRAMMAZIONE MODULARE

Un miglioramento a questo metodo è stato apportato con l’introduzione del concetto di modularità,
rappresentato nella figura sottostante, nel quale un certo numero di procedure con funzionalità simili sono
raggruppati in moduli indipendenti.

Questo è un primo tentativo di separare le procedure e di limitare l’accesso ai dati globali solo ad alcune
specializzate procedure.

Questo approccio alla programmazione ha però ancora notevoli punti deboli specialmente a fronte delle
modifiche che si rendono necessarie in caso di future necessità e di riutilizzo dei programmi.

Ciò è particolarmente vero per applicazioni di grandi dimensioni che a differenza del singolo programma sono
tutt’altro che flessibili anzi di solito sono molto complessi e rigidi e dove un cambiamento in una parte del
programma si propaga per tutta la struttura con effetti difficilmente prevedibili.

64
15.5 LA PROGRAMMAZIONE AD OGGETTI

La programmazione ad oggetti è un modo alternativo di affrontare e scomporre il progetto software. Il suo


paradigma è che l’unità elementare di scomposizione non è più la procedura ma l’oggetto, inteso come modello
di una entità reale.

Quest’ultima operazione, chiamata astrazione, ha un’importanza fondamentale nei linguaggi orientati agli oggetti
ed è uno dei metodi fondamentali con il quale gli esseri umani affrontano i sistemi complessi presenti nel mondo
reale.

L’astrazione è un processo che punta a semplificare un problema complesso e che porta a definire le proprietà
rilevanti di un’entità, ignorando i dettagli non essenziali.

Infatti, per risolvere un problema, non si deve prestare attenzione ad ogni dettaglio ma solo a quelli che portano
alla sua soluzione. Questo significa concentrarsi sulle azioni che un oggetto è in grado di compiere separando il
suo comportamento dai dettagli interni della sua reale implementazione.

Facciamo un esempio di astrazione della vita reale: lo smartphone.

I moderni smartphone sono complessi ma usarli è molto semplice: interagiamo con il telefono attraverso dei
tocchi sullo schermo.

Non ci interessa sapere come è stato costruito e cosa succede all’interno: abbiamo solo bisogno di conoscere
l’insieme di azioni che è possibile effettuare.

Con la programmazione ad oggetti, un sistema complesso viene quindi visto come un insieme di oggetti
interagenti tra loro (tramite messaggi) ciascuno dei quali è provvisto di una sua struttura dati e di un insieme di
operazioni che l’oggetto sa effettuare su tali dati.

65
Siamo passati da un modello orientato al processo, tipico della programmazione procedurale, nel quale
l’attenzione è rivolta alle operazioni da compiere (pur dando importanza ai dati da usare) ad un modello orientato
ai dati che focalizza l’attenzione sui dati da manipolare. Tali dati (astratti) sono oggetti caratterizzati da due
aspetti fondamentali: un insieme di valori e un insieme di operazioni che possono essere applicate all’oggetto.

15.6 VANTAGGI DELLA PROGRAMMAZIONE AD OGGETTI

I principali vantaggi sono:


▪ modellazione software degli oggetti del mondo reale o del modello astratto da riprodurre;
▪ più semplice gestione e manutenzione di progetti di grandi dimensioni;
▪ riusabilità di parti di codice o di moduli funzionali all’interno di altri programmi;
▪ facilità di lettura e di comprensione del codice, anche per persone diverse dall’autore;
▪ robustezza del programma in situazioni critiche o in operazioni che coinvolgono grandi quantità di dati.

La programmazione orientata agli oggetti non presuppone l’eliminazione delle tecniche precedenti, ma piuttosto
le completa, aggiungendo loro una nuova dimensione. Programmare ad oggetti non velocizza l’esecuzione dei
programmi e non ottimizza l’utilizzo della memoria ma facilita la progettazione e la manutenzione di sistemi
software molto complessi.

Il programma, realizzato con orientamento ad oggetti, si sviluppa attraverso le interazioni tra gli oggetti: durante
l’esecuzione del programma, gli oggetti possono cambiare il loro stato (cioè le loro proprietà) e possono
richiedere l’esecuzione di operazioni associate ad altri oggetti.

Cambia quindi la “visione del problema”, cioè, per risolverlo, non si parla più di algoritmo come sequenza di
istruzioni che agiscono su certi dati ma di sistema basato sull’interazione tra entità.

15.7 OGGETTI, METODI E MESSAGGI

Un oggetto può essere definito elencando sia le sue caratteristiche sia il modo con cui interagisce con l’ambiente
esterno, cioè i suoi comportamenti.

Quindi un oggetto possiede:


▪ un insieme di dati (chiamati attributi o proprietà) utili per descrivere le sue caratteristiche e che specificano lo
stato nel quale si trova l’oggetto;
▪ un insieme di operazioni (chiamati metodi) utili per descrivere le azioni che l’oggetto può compiere e che ne
definiscono, quindi, il suo comportamento.

66
Un oggetto comunica con un altro oggetto tramite dei messaggi.

Un messaggio (con eventuali parametri) è una richiesta inviata ad un oggetto allo scopo di attivare delle
operazioni in esso definite. Questo viene realizzato con una chiamata ad un metodo appartenente all’oggetto
ricevente. Il messaggio comunica all’oggetto cosa deve fare (ma è solo l’oggetto ricevente che conosce il modo
nel quale deve agire alla ricezione di un dato messaggio).

Nota: nella pratica gli attributi saranno realizzati attraverso variabili e strutture dati mentre i metodi scrivendo
delle funzioni.

Esempio: oggetto automobile e oggetto autista

Si possono identificare degli attributi che indicano lo stato corrente dell’automobile (luci, marcia, velocità) e dei
metodi per cambiare la marcia, accendere le luci, frenare o accelerare.

L’oggetto “autista”, ai comandi dell’auto, invia messaggi all’oggetto “automobile” utilizzando i suoi metodi
(interruttore delle luci, leva di innesto marcia e pedale dell’acceleratore).

L’oggetto “autista” ignora completamente come queste azioni verranno eseguite (internamente) dall’oggetto
“automobile” ma si limita ad usare gli strumenti che l’automobile mette a disposizione (cioè l’interfaccia
dell’oggetto).

15.8 LA CLASSE

Tutti gli oggetti di uno stesso tipo appartengono alla stessa «famiglia di oggetti» e tutti avranno in comune le
stesse proprietà e le stesse azioni. La classe, quindi, descrive (in maniera astratta) un insieme di oggetti che
condividono gli stessi attributi e metodi.

Un oggetto è una istanza (cioè un esempio) di una data classe che rappresenta, invece, il modo in cui l’oggetto è
stato implementato.

Esempio:

Si vuole gestire l’orario degli arrivi e delle partenze di un aeroporto con un programma che dia la possibilità di
inserire nuovi voli e modificare o cancellare quelli esistenti.

Ciascun volo ha delle caratteristiche (attributi): numero del volo, orario di partenza e di arrivo, provenienza e
destinazione, ecc. Sono previste anche delle azioni (metodi): inserimento (creazione) di un nuovo volo, modifica
delle caratteristiche di un volo, la sua cancellazione e l’eventuale ritardo.

Possiamo rappresentare la classe dei voli con uno schema grafico detto diagramma di classe che ne evidenzia il
nome, gli attributi e i metodi.

67
Dopo aver definito una classe di oggetti è possibile definire uno o più esemplari (istanze) di tale oggetto.

Partendo dalla classe Volo, ad esempio, si possono creare tre istanze, volo1, volo2 e volo3, ottenendo tre oggetti.

Si tratta di tre oggetti che rappresentano in maniera semplificata (sono cioè dei modelli astratti) tre “entità” del
mondo reale. Si tratta di tre entità diverse ma che hanno proprietà uguali (ovviamente con valori diversi) e
possono compiere le stesse azioni (hanno cioè un comportamento simile).

15.9 INCAPSULAMENTO E INFORMATION HIDING

Gli elementi che formano la classe (attributi e metodi) si chiamano membri della classe che rappresenta una unità
di programmazione riutilizzabile in altri programmi.

Chi utilizza gli oggetti di una classe non deve necessariamente conoscere i dettagli implementativi della classe.
Deve sapere, cioè, come si utilizza un oggetto senza per forza conoscerne il suo funzionamento interno.

Questo concetto prende il nome di incapsulamento che indica la tecnica di incorporare all’interno di un oggetto
sia gli attributi che i metodi (cioè caratteristiche e comportamento). Tutto ciò che si riferisce a un certo oggetto
è racchiuso e contenuto nell’oggetto stesso come all’interno di una “capsula” che rende l’oggetto una cosa
distinta dalle cose esterne.

L’incapsulamento si ottiene attraverso il meccanismo detto information hiding che indica il mascheramento delle
modalità di implementazione di un oggetto rendendone disponibili all’esterno solo le funzionalità (di solito la
struttura interna di un oggetto è nascosta come pure l’implementazione dei suoi metodi).

Molto spesso l’oggetto è stato costruito da un programmatore diverso da colui che lo userà a cui interessa
solamente sapere come interagire con l’oggetto, quali sono le sue proprietà e quali metodi mette a disposizione
e come poterli richiamare. In altre parole, l’utilizzatore è interessato all’interfaccia dell’oggetto cioè all’insieme
dei metodi di cui dispone per fornire gli input e ottenere gli output dell’oggetto.

68
15.10 EREDITARIETÀ

Spesso tipi diversi di oggetti hanno delle componenti comuni.

Una moto, un’automobile, una barca e un autobus sono oggetti diversi ma tutti sono veicoli a motore che
condividono alcune caratteristiche (ad esempio cilindrata e potenza del motore, numero di cilindri, ecc.) ma
ognuno ne aggiunge altre di particolari (una moto ha due ruote, auto e autobus quattro mentre una barca
nessuna).

Inoltre, questi veicoli a motore sono a loro volta dei mezzi di trasporto, categoria a cui appartengono anche i
veicoli senza motore come, ad esempio, le bicilette.

Tutto ciò si può schematizzare con un diagramma che rappresenta una gerarchia di classi.

Una classe “figlia” di un’altra classe si dice sottoclasse.

Al contrario una classe “genitore” di altre classi si dice superclasse.

La classe Veicolo a motore, del precedente schema gerarchico, potrebbe essere rappresentata, ad esempio,
come nella figura seguente.

69
Dopo aver implementato una classe di base si può passare alla creazione di una classe più specifica (detta
sottoclasse) che avrà gli stessi attributi e metodi della classe da cui deriva a cui aggiungerà nuovi attributi e nuovi
metodi.

Questo concetto prende il nome di ereditarietà e permette di costruire classi a partire da altre classi. Il vantaggio
di questa tecnica è molto importante perché consente di riutilizzare software già sviluppato e che si ha già a
disposizione aggiungendo nuovi dettagli.

Nell’esempio precedente, l’oggetto Automobile eredita le caratteristiche (attributi) e i comportamenti (metodi)


dall’oggetto Veicolo a motore. Di conseguenza l’oggetto Automobile possiede, per effetto dell’ereditarietà, tutte
le proprietà e le azioni che l’oggetto Veicolo a motore ha messo a disposizione (ad esempio cilindrata e Avvia).

Potranno essere aggiunti membri specifici di una Automobile come, ad esempio, il numero di ruote.

15.11 POLIMORFISMO

Con il termine polimorfismo si intende la caratteristica che possiedono gli oggetti di mostrare un comportamento
diverso nonostante ricevano messaggi identici (cioè esistono oggetti i cui metodi hanno nomi uguali). L’uso di
metodi che presentano lo stesso nome, pur non essendo un vincolo, ha una grande importanza concettuale:
assegnare il medesimo nome a metodi diversi in classi diverse significa aver riconosciuto un comportamento
simile ed ha quindi senso usare lo stesso nome.

Ad esempio, le classi Moto e Automobile potrebbero avere lo stesso metodo Accelera.

Una particolare forma di polimorfismo riguarda, invece, i metodi di una stessa classe.

Nei linguaggi di programmazione tradizionali non possono esistere all’interno dello stesso programma due
funzioni con lo stesso nome. Nei linguaggi orientati agli oggetti, invece, è possibile avere funzioni con lo stesso
nome ma che differiscono per tipo o per numero degli argomenti.

Questo tipo di polimorfismo è noto anche come overloading.

Ad esempio, la classe Automobile potrebbe avere tre metodi “Frena” per individuare tre modi diversi di frenare,
usando il pedale del freno, usando il freno a mano oppure sfruttando il freno motore.

Questi metodi possono avere lo stesso nome ma per “convivere” all’interno della stessa classe devono
differenziarsi, ad esempio, per numero di parametri:
▪ Frena() con il pedale
▪ Frena(mano) con il freno a mano
▪ Frena(motore) con il freno motore

70
15.12 CREAZIONE DI UNA CLASSE

Per definire una classe, il linguaggio Python utilizza la dichiarazione class la cui sintassi generale è la seguente:

class NomeClasse(genitore):
# inizializzazione attributi
...

# definizione metodi
def nome_metodo(self, parametri):
# istruzioni del metodo
...

Gli attributi sono variabili (int, float, stringhe, liste, …) mentre i metodi sono definiti all’interno della classe in
modo simile alle normali funzioni. Il primo parametro self identifica la classe stessa e consente al metodo di
utilizzare i membri della classe stessa.

Tale parametro non va specificato durante la chiamata del metodo che avverrà con la notazione (dot notation)
che abbiamo già utilizzato per gli oggetti di sistema:

nome_oggetto.nome_metodo(...)

In modo analogo l’attributo di un oggetto si identifica con la stessa notazione:

nome_oggetto.nome_attributo

L’utilizzo della classe all’interno del programma avviene attraverso la creazione delle sue istanze, cioè degli
oggetti.

Esempio:

Rappresentare un rettangolo

Creare una classe contenente come attributi base e altezza e due metodi, uno per calcolare il perimetro e uno
per calcolare l’area.

class Rettangolo(object):
# attributi
base=0
altezza=0

# metodi
def perimetro(self):
return 2 * (self.base + self.altezza)

def area(self):
return self.base * self.altezza

71
15.13 CREAZIONE DI UN OGGETTO

La creazione di un oggetto avviene con la chiamata alla classe attraverso una assegnazione:

nome_oggetto = NomeClasse()

Esempio: creazione e utilizzo di un oggetto della classe Rettangolo

tavolo = Rettangolo()
tavolo.base = 10
tavolo.altezza = 20
print("Area del tavolo:", tavolo.area())

15.14 IL COSTRUTTORE

In ogni classe è possibile definire un particolare metodo, detto costruttore, che viene avviato quando si crea un
oggetto. Si tratta di una funzione di inizializzazione dell’oggetto, nella quale si possono preparare tutte le sue
caratteristiche. Dopo aver creato l’oggetto sarà possibile modificare le sue proprietà o invocare l’attivazione dei
suoi metodi.

In python il nome del costruttore è __init__ che deve essere dichiarato come un qualsiasi altro metodo:

def __init__(self,parametri):
# inizializzazione degli attributi

Solitamente nel costruttore vengono create, attraverso la loro inizializzazione, le variabili che rappresentano gli
attributi dell’oggetto. Spesso i valori con cui devono essere inizializzati gli attributi vengono passati come
parametri al costruttore.

Esempio: aggiunta del costruttore alla classe Rettangolo

class Rettangolo(object):
# costruttore
def __init__(self, b=0, h=0): # 0 è il valore di default
self.base = b
self.altezza = h

# metodi
def perimetro(self):
return 2 * (self.base + self.altezza)

def area(self):
return self.base * self.altezza

Non è più necessario definire gli attributi al di fuori dei metodi in quanto verranno creati e inizializzati all’interno
del metodo costruttore. È possibile quindi indicare le dimensione di un oggetto della classe Rettangolo all’atto
della sua creazione:

tavolo = Rettangolo(10,20)

Avendo indicato i valori di default (0) per gli attributi è possibile anche creare un oggetto senza passare valori:

tavolo = Rettangolo() # le dimensioni sono nulle

72
15.15 IL MODULO DELLA CLASSE

Solitamente una classe viene salvata in un file separato il cui nome è di solito uguale al nome della classe (ad
esempio Rettangolo.py).

Per utilizzare la classe all’interno di un programma è necessario importarla (come i moduli), ad esempio:

from Rettangolo import *

15.16 VISIBILITÀ DEI MEMBRI DI UNA CLASSE

Negli esempi precedenti gli attributi della classe Rettangolo erano sempre disponibili al di fuori della classe, ad
esempio nel programma principale:

tavolo.base = 100
tavolo.altezza = 200

È possibile impedire questa possibilità proteggendo gli attributi. Un attributo è protetto (si dice che è privato) se
il suo nome inizia con il doppio underscore (__).

Esempio: classe Rettangolo

class Rettangolo(object):
# attributi privati (protetti)
__base=0
__altezza=0

# metodi pubblici
def dimensioni(self, b, h):
self.__base = b
self.__altezza = h

def perimetro(self):
return 2 * (self.__base + self.__altezza)

def area(self):
return self.__base * self.__altezza

Siccome i membri il cui nome inizia con il doppio underscore non possono essere utilizzati al di fuori della classe,
si è reso necessario aggiungere il metodo dimensioni che consentirà di modificare base e altezza.

Attraverso il doppio underscore è possibile anche creare metodi privati, cioè non disponibili al di fuori della classe,
che solitamente implementano funzionalità interne alla classe che non devono appartenere all’interfaccia messa
a disposizione dall’oggetto verso il mondo esterno.

L’interfaccia è rappresentata esclusivamente dai membri pubblici che possono essere usati per scambiare
messaggi consentendo l’interazione con l’oggetto.

73

Potrebbero piacerti anche