Installare Python - itis magistri cumacini

Transcript

Installare Python - itis magistri cumacini
3
SOMMARIO
INTRODUZIONE E UN PO’ DI STORIA ........................................................................................................................... 3
DIFFERENZE TRA PYTHON 2 E PYTHON 3 .................................................................................................................................. 4
PERCHÉ USARE PYTHON ............................................................................................................................................. 5
PYTHON: I PUNTI DI FORZA .................................................................................................................................................... 5
COSA SI PUÒ FARE CON PYTHON ............................................................................................................................................. 6
CHI USA PYTHON ................................................................................................................................................................. 6
INSTALLARE PYTHON .................................................................................................................................................. 7
INSTALLARE PYTHON SU WINDOWS ........................................................................................................................................ 7
INSTALLARE PYTHON SU LINUX ............................................................................................................................................... 8
INSTALLARE PYTHON SU MAC ................................................................................................................................................ 9
L’INTERPRETE PYTHON E L’IDLE .................................................................................................................................10
ESECUZIONE A RIGA DI COMANDO ......................................................................................................................................... 10
MANDARE IN ESECUZIONE FILE .PY ........................................................................................................................................ 11
USARE L’IDLE .................................................................................................................................................................. 11
LE FUNZIONI PRINT E INPUT ......................................................................................................................................14
PRINT ............................................................................................................................................................................. 14
INPUT ............................................................................................................................................................................. 14
INDENTAZIONE E BLOCCHI DI CODICE IN PYTHON .....................................................................................................16
INDENTAZIONE E BLOCCHI DI CODICE ..................................................................................................................................... 16
VARIABILI E COMMENTI IN PYTHON ..........................................................................................................................18
I COMMENTI IN PYTHON ..................................................................................................................................................... 19
NUMERI E OPERATORI LOGICI IN PYTHON .................................................................................................................20
OPERATORI LOGICI IN PYTHON ............................................................................................................................................. 21
STRINGHE IN PYTHON ................................................................................................................................................22
SLICING E SOTTO-STRINGHE ................................................................................................................................................. 22
METODI PER LE STRINGHE ................................................................................................................................................... 23
COSTRUIRE LE STRINGHE ..................................................................................................................................................... 24
LISTE ..........................................................................................................................................................................25
METODI PER LE LISTE.......................................................................................................................................................... 26
DIZIONARI .................................................................................................................................................................29
INSERIMENTO, MODIFICA E CANCELLAZIONE ............................................................................................................................ 30
METODI PER I DIZIONARI ..................................................................................................................................................... 30
ORDINAMENTO DELLE CHIAVI............................................................................................................................................... 31
TUPLE ........................................................................................................................................................................33
TIPI MUTABILI ................................................................................................................................................................... 33
USARE LE TUPLE ................................................................................................................................................................ 33
A COSA SERVONO LE TUPLE? ................................................................................................................................................ 35
CONVERSIONE LISTE-TUPLE, TUPLE-LISTE ................................................................................................................................ 35
I FILE IN PYTHON .......................................................................................................................................................36
MODALITÀ DI APERTURA DI OPEN ......................................................................................................................................... 37
MUOVERSI ALL’INTERNO DEL FILE ......................................................................................................................................... 37
CICLI E ISTRUZIONI CONDIZIONALI .............................................................................................................................39
IF-ELIF-ELSE ...................................................................................................................................................................... 39
CICLO WHILE .................................................................................................................................................................... 40
CICLO FOR........................................................................................................................................................................ 41
1
FORZARE L’USCITA DAL CICLO ............................................................................................................................................... 42
L’ISTRUZIONE PASS ............................................................................................................................................................ 43
COMPREHENSION PER LISTE E DIZIONARI..................................................................................................................44
ESEMPI DI COMPREHENSION ................................................................................................................................................ 44
FUNZIONI ..................................................................................................................................................................46
DEFINIRE UNA FUNZIONE IN PYTHON ..................................................................................................................................... 46
SCOPE ............................................................................................................................................................................. 46
PASSAGGIO DEI PARAMETRI ................................................................................................................................................. 47
PARAMETRI FACOLTATIVI .................................................................................................................................................... 48
ALTRI ESEMPI.................................................................................................................................................................... 49
MODULI .....................................................................................................................................................................50
SCRIVERE E IMPORTARE UN MODULO..................................................................................................................................... 50
COMPILAZIONE OTTIMIZZATA DEI MODULI .............................................................................................................................. 51
I MODULI STANDARD .......................................................................................................................................................... 51
NAMESPACES ................................................................................................................................................................... 52
GESTIONE DELLE ECCEZIONI .......................................................................................................................................54
CLASSI E CENNI DI PROGRAMMAZIONE AD OGGETTI ................................................................................................56
CLASSI IN PYTHON .....................................................................................................................................................61
APPENDICE ................................................................................................................................................................67
COLORCONSOLE ................................................................................................................................................................ 67
LA GRAFICA ...................................................................................................................................................................... 68
2
Introduzione e un po’ di storia
Python è un linguaggio di programmazione moderno, dalla sintassi semplice e potente che ne
facilita l’apprendimento. Gli ambiti di applicazione sono svariati: Python è attualmente utilizzato
per realizzare interfacce GUI, per lavorare con i database, per lo sviluppo di applicazioni Web e
desktop, per realizzare giochi, grafica 3D, etc.
L’obiettivo di questa guida è quello di fornire una panoramica generale sulla programmazione in
Python, che permetta al lettore di sviluppare in modo facile e veloce delle proprie applicazioni.
Nota: Questa è la riedizione della guida Python di Stefano Riccio, revisionata e aggiornata da
Andrea Sindoni e dalla redazione di HTML.it
Prima di iniziare, può essere utile capire come e dove è nato Python. Per farlo bisogna tornare un
po’ indietro nel tempo precisamente nei primi anni ottanta, in quegli anni al National Research
Institute for Mathematics and Computer Science (CWI) di Amsterdam, alcuni ricercatori tra cui
Guido Van Rossum hanno sviluppato un linguaggio di nome ABC, molto potente ed elegante che
era diventato popolare nel mondo Unix.
Qualche anno dopo (fine anni ottanta) Guido Van Rossum ha avuto una serie di idee mirate al
miglioramento di ABC, pertanto si mise a lavorare allo sviluppo di un nuovo linguaggio: Python.
Nel 1996 scrisse come prefazione del libro “Programming Python”, prima edizione, le seguenti
parole:
«Più di sei anni fa, nel dicembre 1989, stavo cercando un progetto di programmazione per
“hobby” che mi avrebbe dovuto tenere occupato nella settimana vicina a Natale. Il mio ufficio…
sarebbe stato chiuso, ma io avevo un computer, e non molto di più. Decisi di scrivere un
interprete per un nuovo linguaggio di scripting a cui avrei pensato dopo: un discendente
dell’ABC, che sarebbe dovuto appartenere agli hacker di Unix. Scelsi Python come nome per il
progetto, essendo leggermente irriverente (e sono un grande fan di monty Python’s Flying
Circus).»
Nel 2000 Van Rossum e il suo team si trasferiscono presso BeOpen.com e formano i BeOpen
PythonLabs team con Python arrivato alla versione 1.6. Qualche tempo dopo viene rilasciata la
versione 2.0, una delle principali aggiunte in questa versione è quella delle “list comprehension“.
Nel 2001 viene rilasciato Python 2.1 e ridefinita la licenza con “Python Software Foundation
License”. Python 2.2 fu considerato un “rilascio puliza”, ci sono molte novità ma sicuramente la
principale è l’unificazione dei tipi/classi.
Bisogna arrivare al Dicembre 2008 per assistere ad una vera rivoluzione, con il rilascio della
versione 3.0 di Python (o “Python 3000″ o “Py3k”). Questa nuova versione ha rotto la
compatibilità con le vecchie versioni 2.X. Vediamo di seguito alcuni di questi importanti
cambiamenti.
3
Differenze tra Python 2 e Python 3
Alcune delle novità introdotte con Python 3.X hanno segnato una discontinuità nella compatibilità con le
versioni precedenti (2.x). Ci sono cambiamenti facili da segnalare, come la modifica dell’istruzione print in
funzione print, altri invece sono molto delicati come ad esempio il cambiamento del tipo stringa in tipo byte
(sequenza di byte).
Ecco una tabella che mostra i principali cambiamenti tra le due versioni:
Python 2.X
Python 3.X
Print "x" (senza parentesi)
X <> Y
Print("x")
Long
Int
raw_input()
input()
try...except Exception, e
try...except Exception as e
Raise Exception, "Errore"
Raise Exception("Errore")
standardError class
Exception class
import mod
from . import mod
my_dict.keys() ritorna liste
unicode("ciao")
my_dict.keys() ritorna viste dinamiche
str("ciao")
>>>k={1:"andrea", 5:"giuseppe"}
>>>1 in k
True
import httplib
>>>k={1:"andrea", 5:"giuseppe"}
>>>k.has_key(1)
True
import http.client
import constant
from . Import constant
types.UnicodeType
Str
types.StringType
bytes
types.IntType
int
types.LongType
int
X != Y
È possibile trovare in dettaglio tutte le novità della versione 3.X dal sito ufficiale, nei prossimi
capitoli della guida vedremo più nel dettaglio e nella pratica alcuni di questi cambiamenti.
4
Perché usare Python
Oggi esistono numerosi linguaggi di programmazione, ma cosa spinge ad usare Python, cosa c’è di
particolare in questo linguaggio? Per rendercene conto, in questa lezione esaminiamo alcuni dei
punti di forza di Python ed alcune delle sue applicazioni principali.
Python: i punti di forza
 free
Python è completamente gratuito ed è possibile usarlo e distribuirlo senza restrizioni di
copyright. Spesso alla parola “free” è associato il concetto di “software non supportato”, ma
questo non è assolutamente vero nel caso di Python: è sufficiente consultare periodicamente il
sito ufficiale per rendersene conto.
 orientato agli oggetti
Python è un linguaggio orientato agli oggetti, supporta nozioni avanzate di polimorfismo,
ereditarietà, operatori di overloading il tutto con una semplice sintassi.
 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 Nokia e
Android, questo perché è interpretato, quindi lo stesso codice può essere eseguito su qualsiasi
piattaforma purché abbia l’interprete Python installato.
 facile da usare
Chi ha programmato in altri linguaggi di programmazione troverà Python semplice da usare,
questo grazie alle semplici regole di sintassi e al fatto che generale si opera ad un alto livello di
astrazione.
 ricco di librerie
La dotazione standard offre numerose librerie alle quali si aggiungono moduli di terze parti che
crescono continuamente. In Internet si trova materiale relativo a HTML, PDF, XML, formati
grafici, CGI e perfino interi Web Server.
 performante
Python è un linguaggio interpretato. In questo caso “interpretato” non è sinonimo di lento,
infatti Python “compila” il proprio codice in un bytecode molto efficiente. Questo permette di
raggiungere prestazioni vicine ai linguaggi in codice nativo. Inoltre Python implementa molte
strutture dati e funzioni come componente intrinseca del linguaggio. Queste strutture sono
dette “built-in types and tools” e sono state sviluppate con accurata efficienza.
 gestisce la memoria automaticamente
Come in Java, in Python esiste il meccanismo di “garbage collection“, che permette di liberare il
programmatore dall’ansia di allocazione selvaggia della memoria.
 integrabile con altri linguaggi
Python può essere integrato ad altri linguaggi come .NET con IronPython o Python per .NET,
Java con Jython
5
Cosa si può fare con Python
Come abbiamo accennato la dotazione standard e le librerie di terze parti, completano Python con
funzionalità che lo rendono uno strumento duttile in svariati ambiti, osserviamone alcuni più da
vicino:
 Programmazione GUI
Ecco alcune delle possibili librerie da utilizzare per sviluppare interfacce utente:
- TkInter, la libreria GUI open source più usata. Gli script Python che usano TkInter sono portabili quindi
avviabili su piattoforma Windows, Linux, Unix, Mac
- PyQt, è la versione Python di Qt, il framework multipiattaforma storicamente realizzato da Nokia, quindi
avviabile su piattaforme sia desktop (Win, Mac, Linux), sia mobile (Symbian)
- wxPython, è un interfaccia Python per la libreria wxWidgets, anch’essa portabile e quindi avviabile sulle
diverse piattaforme
 Sviluppo Web
Esistono svariate possibilità per lo sviluppo Web sia ad alto che a basso livello. Ad alto livello
esistono i web framework come:
- Django è un ottimo framework Web, ha un sito ben curato e si trova molta documentazione,
- Web2py altro ottimo framework facile da usare.
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.
Mentre se si vuole scendere più a basso livello esistono le interfacce socket ma anche alcuni
framework che aiutano la programmazione di rete, uno fra tutti è Twisted: un potente network
engine, event-driven – scritto in Python – che supporta molti protocolli di rete inclusi SMTP, POP3,
IMAP, SSHv2 e DNS.
È possibile usare Python anche per accedere ai database (mediante delle interfacce ODBC con
Oracle, mysql, PostgreSQL e altri), per la realizzazione di giochi (pygame e pykyra sono due ottimi
framework che permettono lo sviluppo in modo semplice e intuitivo), per realizzare applicazioni
scientifiche (SciPy è un tool open source per matematica, scienze e ingegneria), per grafica 3D e in
tanti altri campi.
Chi usa Python
Python risulta un ottima soluzione per amministratori di sistema abituati ad usare linguaggi di
scripting come Perl, Bash, Tlc, etc, è altrettanto un ottima soluzione per lo sviluppatori software
che usano linguaggi come (C, C++, Java, etc).
Oggi Python viene utilizzato in molte grandi realtà del mercato informatico, eccone alcuni esempi:



6
La NASA usa Python per lo sviluppo di sistemi di controllo;
Yahoo! ha sviluppato in Python alcuni servizi di internet;
Google, Youtube, RedHat usano Python.
Installare Python
La versione di Python che andremo ad usare in questa guida è la 3.2.3 che si può liberamente
scaricare dal sito ufficiale: http://www.Python.org/
Installare Python su Windows
Nella pagina di download è possibile trovare il file .msi per le versioni Windows a 32bit e 64bit. È
sufficiente lanciarlo. Dopo l’installazione, Python di default viene collocato in C:\Python32. A
questo punto è già possibile utilizzarlo da: Start->Tutti i programmi->Python3.2->Python.
Se si vuole però avviare Python senza problemi da una finestra DOS, bisogna andare in: Pannello
di controllo->Sistema->Impostazioni di Sistema Avanzate->Variabili d'ambiente
Quindi modificare la variabile Path dalle variabili di sistema aggiungendo C:\Python32.
Adesso se si vuole verificare che tutto è andato a buon fine, avviare il prompt dei comandi (Start>Esegui->cmd) e digitare:
echo %PATH%
quindi se si ritrova la variabile C:\Python32 è possibile avviare Python digitando semplicemente
Python.
7
Installare Python su Linux
Nei sistemi Linux spesso Python è già presente nel setup di base, è comunque possibile verificare
che ci sia digitando da shell:
$ Python
Se il comando sarà riconosciuto, avremo lanciato l’interprete iterattivo di Python, che si
presenterà con il consueto prompt composto di 3 caratteri “maggiore” ( >>> ).
Se invece il comando non sarà riconosciuto, sarà necessario installarlo usando il gestore dei
pacchetti per sistemi Linux, apt per distribuzioni basate su Debian, rpm per distribuzioni basate su
Red Hat, oppure compilare i sorgenti.
Vediamo più nel dettaglio l’installazione da Package, in base al sistema in uso è possibile avviare
uno dei seguenti comandi:
Comando
$ yum install Python3
$ apt-get install Python3
Descrizione
(per distribuzioni basate su pacchetti rpm, come Red Hat, Fedora, Centos)
(per distribuzioni basate su Debian, come Ubuntu)
Infine vediamo come installare Python compilando i sorgenti.
Per prima cosa verificare l’ultima versione dei sorgenti dal sito , quindi lanciare i seguenti comandi:
$ cd /tmp
$ wget http://www.Python.org/ftp/Python/3.x/Python-3.x.tar.bz2
ed estrarre il contenuto:
8
$ tar -xjf Python-3.x.tar.bz2
$ cd Python-3.x
$ ./configure
$ make
$ sudo make install
Installare Python su Mac
Come nei sistemi Linux, anche nei Mac dovremmo trovare Python già pronto all’uso. Per verificare
al solito basta avviare una finestra di terminale e digitare Python, è probabile che appaia la
versione 2.7, ma noi vogliamo usare la 3.2.3. Quindi bisognerà andare sul sito e scaricare la
versione per MAC OS più adatta alle nostre esigenze, infine procedere all’installazione.
Al termine dell’installazione, lanciando Python da terminale apparirà ancora la vecchia versione,
pertanto bisogna aprire il terminale e digitare:
vim ~/.bash_profile
Una volta aperto il file, aggiungere la seguente riga:
alias Python="Python3"
Ora provando di nuovo a lanciare Python da terminale, per default si avvierà la versione 3.2.3.
9
L’interprete Python e l’IDLE
Come abbiamo visto nelle lezioni precedenti, se lanciamo il comando Python da riga di comando
sia in ambiente Windows che Linux, si avvia quello che da adesso chiameremo “interprete
interattivo“, dall’aspetto del tutto simile ad un’altra riga di comando. Appare uno specifico
prompt, caratterizzato da 3 caratteri di maggiore (>>>).
In altre parole un interprete Python è un programma che permette l’esecuzione di altri
programmi. È interessante aprire una piccola parentesi su quello che succede quando si esegue un
programma scendendo un po’ più nel dettaglio.
Ogni volta che viene invocato il comando Python il codice scritto viene scansionato per token,
questi token vengono analizzati dentro una struttura ad albero che rappresenta la struttura logica
del programma, che in fine viene trasformata in bytecode (file .pyc o .pyo). Per potere eseguire
questi bytecode serve un interprete bytecode che è una macchina virtuale Python(PVM).
Sorgente (file.py) -> Bytecode(file.pyc) -> Runtime(PVM)
Esecuzione a riga di comando
Torniamo a concentrarci sul funzionamento base dell’interprete Python. La caratteristica
fondamentale è che digitando dei comandi si ottiene subito una risposta, ecco degli esempi:
>>>
5*3
15
>>> a=5
>>> b=6
>>> 2*(a+b)+3*a
37
10
Mandare in esecuzione file .py
Ma come si fa a creare ad eseguire un file Python? Per prima cosa bisogna creare un file di testo (ASCII) e
salvarlo con estensione “.py“, per esempio possiamo chiamare un file helloworld.py. A questo punto
possiamo aprire il file creato con un qualsiasi editor di testi (non Word, ma notepad o simili) e scrivere:
print('Hello World!!')
Il file contiene una sola riga di codice con la funzione print(), che come risultato stamperà una
stringa. Eseguiamo il file:
C:\Python32>Python helloworld.py
Hello World!!
Usare l’IDLE
Ora che abbiamo visto brevemente come eseguire un file Python da command line, possiamo
esaminare un ambiente visuale che permette di modificare, eseguire e fare il debug di un
programma Python da un’unica interfaccia: l’Integrated Development Environment (IDLE).
L’IDLE è un ambiente GUI Python eseguibile in ambiente Windows, Linux, MAC OS. Esso viene
avviato da uno script Python (idle.pyw) nel caso di Windows 7 ad esempio si trova in:
C:\Python32\Lib\idlelib\
È possibile però lanciarlo in modo veloce dal menu Start->Tutti i Programmi->Python 3.2.
Avviando l’IDLE apparirà una finestra con l’ormai noto prompt dei comandi Python (>>>), e le voci
di menu che si è abituati a vedere in altre applicazioni.
11
Iniziamo a prendere confidenza con questo strumento.
Aprire e lanciare un file
Come appare naturale, per aprire un file Python possiamo agire da menu File->Open (Ctrl+O),
per crearne uno nuovo utilizziamo File->New Window (Ctrl+N). In entrambe i casi sarà presente
tra i comandi menu Run. Selezionado Run->RunModule (F5) sarà possibile eseguire lo script.
Personalizzare l’IDE
Sarà importante anche personalizzare l’aspetto estetico dell’IDE, per lavorare con il maggior
comfort possibile. Per questo andiamo da menu su Options->Configure IDLE
12
Possiamo scegliere il tipo Font, la larghezza dell’indentazione (più avanti vedremo di cosa si tratta)
dal tab Fonts/Tabs, i colori delle parole chiave, delle stringhe, dei commenti, delle definizioni, degli
errori e altri dal tab Highlighting.
13
Le funzioni print e input
In questa lezione facciamo la conoscenza di due funzioni basilari di Python: print e input. Utilissime
soprattutto a supporto della creazione dei primi test e programmi a riga di comando.
Print
Abbiamo già trovato nelle passate lezioni la funzione print(), che serve a “stampare” in output
(tipicamente sullo schermo) il valore di una variabile o di una espressione.
>>> a = 12
>>> b = 3
>>> print(a,b,(a - b))
12 3 9
Si noti la flessibilità del comando print, il quale concatena il valore di diversi parametri suddivisi
dalla virgola e li mostra in output.
Nota: nelle precedenti versioni di Python print era un comando e non una funzione e non era
necessario inserire i parametri tra parentesi, mentre ora omettere le parentesi significa
commettere un errore di sintassi.
Quando si lavora a riga di comando è sufficiente digitare il nome della variabile per stamparne il
valore. Questa possibilità offerta dalla modalità interattiva, consente un debug un po’ più snello.
Quando si esegue un programma è necessario utilizzare il print.
>>> x=10
>>> x
10
Input
Se realizziamo piccoli programmi da utilizzare da console o riga di comando, risulta utile la
funzione input, che serve ad intercettare le sequenze inserite nello std-in, quindi tipicamente da
tastiera.
Ecco due esempi:
>>> valore = eval(input('Inserisci un valore numerico:'))
Inserisci un valore numerico: 5
>>> print(valore*valore)
25
14
>>> valore = input('Inserisci una stringa:')
Inserisci una stringa: html.it
>>> print(valore)
html.it
Nota: In passato il comando input serviva per l’acquisizione di variabili numeriche, mentre per le
sequenze e le stringhe si utilizzava raw_input. Nella versione 3 di Python il comando
raw_input diventa input. Per ottenere il precedente comportamento di input occorre
scrivere eval(input(...))
15
Indentazione e blocchi di codice in Python
In questa lezione vediamo alcuni degli aspetti fondamentali da tener presente nella
programmazione con Python, il più importante certamente è la caratterizzazione dei blocchi di
codice attraverso l’indentazione del testo, una pratica che può spiazzare chi viene da altri linguaggi
di programmazione in cui si delimitano i blocchi con parentesi graffe, begin-end o altri costrutti.
Vedremo anche come dichiarare le variabili e commentare il codice.
Indentazione e blocchi di codice
Python è stato progettato e realizzato per essere un linguaggio chiaro e leggibile, per questo è
stato scelto di utilizzare l’indentazione per definire i blocchi di codice o il contenuto dei cicli di
controllo.
All’inizio ci si può confondere con l’indentazione e i blocchi, e può anche capitare che gli spazi,
l’indentazione cambiano in funzione dell’editor che si usa, ma il vantaggio è quello di avere un alta
leggibilità del codice, proprio perché si è obbligati ad indentare i sorgenti.
Vediamo in generale come viene rappresentata l’indentazione di blocchi nel caso dei cicli di
controllo:
istruzione:
blocco
istruzione:
blocco
È molto importante fare attenzione all’indentazione quindi, perché viene considerata nel processo
di parsing del programma, ecco cosa succede se introduciamo qualche inesattezza:
16
Spazi o tabulazioni?
Le indentazioni devono essere fatte utilizzando gli Spazi. Così è indicato anche nelle guideline
ufficiali e la motivazione principale sta nel fatto che non c’è uniformità di rappresentazione delle
tabulazioni tra diversi editor, il ché potrebbe indurre in errore anche il più attento dei
programmatori.
Quanti spazi?
In genere si utilizzano indentazioni di quattro spazi, ma possiamo decidere arbitrariamente, ciò
che conta è che siano coerenti i livelli di indentazione, ovvero le distanza tra le istruzioni interne al
blocco di codice e quelle esterne.
Se pensate di mettere a disposizione il vostro codice ad altri sviluppatori, al di fuori di un team, è
consigliabile adeguarsi ai 4 spazi canonici, mentre se si fa parte di un team di sviluppo sarebbe
utile, ma è anche ovvio, che tutti condividano lo stesso stile per le indentazioni.
Altra cosa sono gli spazi utilizzati all’interno delle istruzioni, per i quali invece abbiamo piena
libertà, nel rispetto della sintassi. Ad esempio, all’interno della definizione di un array possiamo
utilizzare anche una indentazione di questo tipo:
>>> vec = [
'uno',
'dieci',
'cinque'
]
>>> print(vec)
['uno', 'dieci', 'cinque']
17
Variabili e commenti in Python
In Python non è necessario definire le variabili prima di utilizzarle e nemmeno assegnare ad esse
un tipo. Il tutto avviene implicitamente mediante l’istruzione di assegnamento (=), un po’ come in
JavaScript o nel vecchio Basic.
Python possiede tutti i classici tipi di dati, comuni agli altri linguaggi. Ecco una tabella che riassume
le caratteristiche principali dei tipi di dati disponibili:
tipo di dato
rappresentazione interna
esempi
oltre 32 bit con crescita in base alle esigenze 999999999, 1200, -56, 0
Intero
Reale
32 bit (tipo double del C)
1.23 3.14e-10, 4.0E210
Booleano
intero con 1=VERO e 0=FALSO (come in C)
0, 1
Complesso
coppia di numeri reali
3+4j, 5.0+4.1j, 3j
Stringhe
lista di caratteri
'stefano', "l'acqua"
Ricordiamo che le regole da seguire nella scelta dei nomi delle variabili è simile a quella dei più
comuni linguaggi di programmazione, in particolare:



Ogni variabile deve iniziare con una lettera oppure con il carattere underscore “_”, dopodiche’
possono seguire lettere e numeri o il solito underscore.
Python è un linguaggio case sensitive, quindi distingue le variabili composte da caratteri minuscoli
da quelle scritte con caratteri maiuscoli.
Esistono delle parole riservate che non possono essere utilizzate per i nomi delle variabili. Esse sono
e seguenti:
False, None, True, and, as, assert, break, class, continue, def, del,
elif, else, except, exec, finally, for, from, global, if, import, in,
is, lambda, nonlocal, not, or, pass, print, raise, return, try, while, with, yield
In Python è possibile assegnare un valore ad una variabile mediante l’operatore “=“.
Assegnamento multiplo
Una singolare possibilità offerta da Python è rappresentata dall’assegnamento multiplo nel quale
si possono inizializzare più variabili direttamente sulla stessa riga di codice.
>>> a = 'viva Python'
>>> b = 3
>>> c, d = 'su', 'HTML.it' # assegnamento multiplo
>>> print (a,b,c,d)
viva Python 3 su HTML.it
cognome, nome = input("Inserisci cognome e nome: ").split()
>>> print (nome,cognome) #supponendo di ave inserito: Simpson Homer
Homer Simpson
18
I commenti in Python
È sempre buona norma commentare il codice, e quindi anche Python offre una sintassi per i
commenti. Il carattere che identifica il commento è : “#“. esso si può usare all’inizio della riga
oppure alla fine di una istruzione.
# Questo è un commento all'inizio della riga
# si possono fare quante righe si preferisce
a = 3 # Questo è un commento che segue l'istruzione di assegnamento
19
Numeri e operatori logici in Python
Python offre quattro possibilità per rappresentare i numeri: interi, razionali, complessi e booleani.
Nota: Nelle versioni precedenti di Python esisteva una distinzione tra intero (int)e “intero
lungo” (long), da Python 3 si parla solo di int che corrisponde al vecchio long (in pratica long
è stato rinominato int).
Oltre a questi tipi di dati “semplici”, Python offre la possibilità di dichiarare anche strutture dati
complesse implementate in modo nativo (“built-in types” come si dice ufficialmente): liste,
dizionari, tuple e files; che esamineremo nelle prossime lezioni.
L’aritmetica utilizzata è molto simile a quella del C, facciamo qualche esempio:
>>> 6+4*3
18
>>> 9/2
# la divisione tra due numeri interi restituisce un float
4.5
>>> 2j * 2j
# moltiplicazione tra numeri complessi
(-4+0j)
>>> int(10.6)
# conversione esplicita dal tipo float al tipo int
10
>>> float(20)
# conversione esplicita dal tipo int al tipo float
20.0
Le operazioni sui tipi numerici sono le più classiche:
Operatore
+ -
somma e sottrazione
Esempi
10+12=22
5-1=4
moltiplicazione e divisione
10*12=120
10/2=5
%
resto della divisione
10%3=1
5.3%2.5=0.3
//
divisione intera
10//3=3
shift bit a bit a sinistra e destra
24<<1=48
10>>1=5
* /
<< >>
20
Descrizione
Operatori logici in Python
Per gli operatori logici (booleani) abbiamo:
Operatore
Descrizione
or e and logici
or and
<
<= >
not
>= ==
¦
&
^
negazione logica
<>
!=
Esempi
x or y
z and k
(not 0)=1
or bit a bit
(10==10)=1
('a’!='a’=0
x ¦ y
and bit a bit
x & y
or esclusivo bit a bit
x ^ y
operatori di confronto
21
Stringhe in Python
In questa lezione ci occupiamo di come trattare le stringhe in Python. Abbiamo già visto che per
dichiarare una stringa sia sufficiente assegnare ad una nuova variabile un testo racchiuso tra
virgolette: è possibile racchiudere il suo valore indifferentemente tra apici ' o doppi apici “
Questo permette di superare facilmente il problema dell’utilizzo dei suddetti caratteri nel valore
stesso della stringa. Ricordo comunque che è possibile forzare l’inserimento di ognuno dei due
apici semplicemente raddoppiandoli.
Per iniziare ad approfondire un po’, iniziamo col dire che le stringhe possono essere considerate
come sequenze di caratteri (liste), è pertanto possibile prelevare i caratteri attraverso il loro
indice, tenendo presente che si parte sempre da 0.
Slicing e sotto-stringhe
Ancora più interessante è la possibilità di prelevare sottostringhe utilizzando la tecnica dello
“slicing” (affettare). Questa tecnica permette di tagliare una parte della lista indicando l’indice di
partenza e l’indice finale.
È utile sapere però che la sotto-stringa prelevata è quella che va dal carattere indicato del primo
indice incluso, fino quello dell’indice finale escluso. Omettendo uno dei due indici indichiamo a
Python di andare fino in fondo alla stringa. Infine, se inseriamo un numero negativo come indice
finale, Python conterà i caratteri a ritroso.
Operatore
+
*
s[i]
Descrizione
concatenamento
('a'+'b')='ab'
ripetizione
('a'*3)='aaa'
indicizzazione dei caratteri
s='abc'
s[0]= 'a'
s='abc'
s[1:2]='b'
s='abc'
len(s)=3
s[i:j]
slicing
len(s)
lunghezza
%
formattazione di stringhe
Esempio
(‘ciao %s’ % ‘stefano’)=’ciao stefano’
Ecco qualche esempio pratico:
>>> y='ciao mondo'
>>> y[0] # prende la prima lettera di y tenendo presente che si parte da 0
'c'
>>> y[5]
'm'
22
>>> x='programmazione Python'
>>> x[-2] # stampa il secondo carattere partendo da destra
'o'
>>> x[2:7] # stampa i caratteri di x compresi da 2 a 7 (escluso)
'ogram'
>>> x[4:] # stampa dal quarto carattere alla fine di x
'rammazione Python'
>>> x[:4] # stampa i caratteri di x compresi dall'inizio al quarto (escluso)
'prog'
>>> x[3:-2] # stampa dal terzo carattere (contando da 0) al penultimo di x
(escluso)
'grammazione pyth'
Metodi per le stringhe
Osserviamo ora alcuni metodi per le stringhe che possono tornare utili.
Il metodo find() serve a ricercare dei caratteri da una stringa (restituisce -1 se non è presente)
>>> s='html.it'
>>> s.find('html')
0
Il metodo replace() serve a sostituire dei caratteri in una stringa.
>>> s.replace('it','test')
'html.test'
I metodi upper() e lower() servono invece a convertire in maiuscolo e minuscolo una stringa.
>>> up=s.upper()
>>> print(up)
HTML.IT
>>> low=up.lower()
>>> print(low)
html.it
23
Costruire le stringhe
Grazie all’operatore percentuale (%) possiamo costruire una stringa inserendo dei parametri
“segnaposto” da sostituire con i valori assunti da variabili, come avviene nella istruzione printf del
C. Facciamo subito qualche esempio complesso per osservarne il funzionamento:
>>> nome = 'stefano'
>>> eta = 29
>>> risultato = "%s ha %d anni" % (nome, eta)
>>> print(risultato)
stefano ha 29 anni
Nelle prime righe abbiamo definito le variabili e assegnato valori stringa e numerici. Nella stringa
“%s ha %d anni” abbiamo inserito i parametri:


%s : parametro di tipo stringa
%d : parametro di tipo numerico
Parametri per la costruzione delle stringhe
Parametro
%s
%c
%d
%u
%o
%x
%g
%e
Descrizione
stringa
singolo carattere
numero decimale
intero senza segno
numero in notazione ottale
numero in notazione esadecimale
numero reale in notazione normale
numero reale in notazione scientifica
Python offre altre funzioni per gestire le stringhe, esse sono tutte raggruppate nel modulo
denominato “string”. Non avendo ancora parlato di moduli, introdurremo queste funzioni in
seguito.
24
Liste
Le liste in Python sono collezioni ordinate di oggetti, simili agli array di altri linguaggi di
programmazione. In altre parole permettono di memorizzare una sequenza gli oggetti ed accedere
ad essi mediante un indice.
A differenza delle stringhe che abbiamo trattato, le liste possono contenere oggetti eterogenei
come numeri, stringhe e altre liste. Questo consente di manipolare con agilità strutture complesse
con dati di diversa natura.
Per dichiarare una lista è sufficiente assegnare ad una variabile un elenco di valori, separati da
virgola e racchiusi da parentesi quadre. Ecco un paio di esempi:
>>> l1=[1, 'html.it'] # lista con un intero e una stringa
>>> l2=[1, 1.2, 'ciao', [1,2] ] # lista con: intero, reale, stringa e un'altra
lista
Molto di quanto detto per le stringhe vale anche per le liste, come l’indice che inizia da 0. Gli
esempi seguenti illustrano gli operatori di indicizzazione e slicing che abbiamo già visto per le
stringhe.
>>> s=['html', 'it', 'html.it']
>>> s[0]
# indicizzazione
'html'
>>> s[-2]
# indicizzazione contando da destra
'it'
>>> s[:2]
# slicing
['html', 'it']
>>> s[2:]
['html.it']
>>> s[1:-1]
['it']
Vediamo adesso gli operatori per la concatenzazione “+” e ripetizione “” per le liste:
>>> [1, 2, 3] + [4, 5] # concatenazione
[1, 2, 3, 4, 5]
>>> ['html.it']*3
# ripetizione
25
['html.it', 'html.it', 'html.it']
Si possono anche modificare, eliminare degli elementi da una lista tramite l’indicizzazione:
>>> y=[1,2,3]
>>> y[0]="uno" # modifica della lista
>>> y
['uno', 2, 3]
>>> y[1:2]=[]
# cancello un elemento dalla lista
>>> y
['uno', 3]
Per conoscere la lunghezza di una lista utilizziamo la funzione len() :
>>> lista=['c', 'a', 'b']
>>> len(lista)
3
Metodi per le liste
 INSERIMENTO
Metodo
Descrizione
append(oggetto)
Aggiunge un oggetto in coda alla lista
extend(lista)
Collega un’altra lista in coda alla lista
insert(indice ,oggetto)
Inserisce un oggetto in testa alla lista
Esempi:
>>> lista=['html', 'HTML', 'Html']
>>> lista.append('html.it')
#metodo append()
>>> lista
['html', 'HTML', 'Html', 'html.it']
>>> lista.extend(['HYml','html.IT'])
>>> lista
['html', 'HTML', 'Html', 'html.it', 'HYml', 'html.IT']
26
#metodo extend()
>>> lista.insert(0, 'primoHTML')
#metodo insert()
>>> lista
['primoHTML', 'html', 'HTML', 'Html', 'html.it', 'HYml', 'html.IT']
 CANCELLAZIONE
Metodo
pop([indice])
remove(valore)
Descrizione
Restituisce l’oggetto della lista con l’indice
specificato, poi lo rimuove dalla lista. Se l’indice
non è specificato, pop elimina e restituisce l’ultimo
elemento della lista.
Elimina dalla lista il valore passato
Esempi:
>>> lista=['html', 'HTML', 'Html']
>>> lista.pop() #senza indice elimina l'ultimo elemento della lista
'Html'
>>> lista
['html', 'HTML']
>>> lista=['html', 'HTML', 'Html']
>>> lista.remove('html')
['HTML', 'Html']
>>> lista=['html', 'HTML', 'Html']
>>> lista.remove(lista[1])
>>> lista
['html', 'Html']
27
 ORDINAMENTO
Metodo
sort()
Descrizione
Restituisce la lista ordinata in ordine
crescente
>>> lista=['c', 'a', 'b']
>>> lista.sort()
>>> lista
['a', 'b', 'c']
28
Esempi:
Dizionari
Un dizionario rappresenta una collezione “non ordinata” di oggetti. Gli oggetti sono identificati
univocamente da una chiave (generalmente una stringa) invece che mediante un indice numerico,
come avviene nelle liste.
Ogni elemento del dizionario è rappresentato da una coppia (chiave : valore), la chiave serve per
accedere all’elemento e recuperare il valore.
Esattamente ciò che avviene quando si cerca una parola sul vocabolario, in tal caso il valore che si
cerca è una frase che spiega il significato della chiave. Per fare un parallelo con altri linguaggi si
può pensare al dizionario come ad una specie di array associativo.
Dal punto di vista computazionale è vantaggioso utilizzare i dizionari perché sono delle tabelle
hash. Come il tipo hash in Perl, le istanze di Hashtable in Java o C#, le mappe MFC per Visual C++,
etc.
In analogia alle liste, anche per i dizionari Python lascia la possibilità di inserire oggetti eterogenei
nella stesso dizionario.
Un dizionario si rappresenta con gli elementi separati da virgole e racchiusi in parentesi graffe, un
dizionario vuoto è rappresentato dalle parentesi aperte e chiuse:
>>> diz1={}
# dizionario vuoto
>>> diz1
{}
Possiamo creare un dizionario vuoto anche sfruttando il metodo dict():
>>> diz2=dict()
# dizionario vuoto
>>> diz2
{}
Possiamo definire gli elementi del dizionario direttamente elencando le coppie chiave-valore:
>>> diz={'html':1, 'HTML':2, 'HTml':3}
>>> diz
{'html': 1, 'HTML': 2, 'HTml': 3}
Per recuperare un valore possiamo poi passare al dizionario il nome della chiave relativa.
>>> diz['HTML']
# recupera il valore partendo dalla chiave
2
29
Possiamo verificare l’esistenza di una certa chiave nel dizionario con la keyword in:
>>>
'html' in diz
# ricerca la chiave
>>> True
Inserimento, modifica e cancellazione
Vediamo adesso come si fa a inserire, modificare e cancellare gli elementi di un dizionario.
>>> diz={'html':1, 'HTML':2, 'HTml':3}
>>> diz['html.it']=4
# inserimento
>>> diz
{'html': 1, 'HTML': 2, 'html.it': 4, 'HTml': 3}
>>> diz['html']=7
# modifica
>>> diz
{'html': 7, 'HTML': 2, 'html.it': 4, 'HTml': 3}
>>> del diz['HTML']
# cancellazione
>>> diz
{'html': 7, 'html.it': 4, 'HTml': 3}
Per conoscere il numero di elementi di un dizionario possiamo utilizzare la consueta funzione len.
>>> len(diz)
3
Metodi per i dizionari
Vediamo ora quali sono i metodi principali dei dizionari:
Campo
Descrizione
get(‘chiave’) restituisce il valore della chiave inserita
30
values()
restituisce l’elenco dei valori del dizionario
keys()
restituisce l’elenco delle chiavi del dizionario
items()
restituisce una lista di tuple per ogni coppia
>>> diz={'html.it':1, 'HTML':2, 'html':3}
>>> diz.get('html')
# metodo get()
3
>>> diz.values()
# metodo values()
dict_values([1, 3, 2])
>>> diz.keys()
# metodo keys()
dict_keys(['html.it', 'html', 'HTML'])
>>> diz.items()
# metodo items()
dict_items([('html.it', 1), ('html', 3), ('HTML', 2)])
Ordinamento delle chiavi
A differenza di quanto accadeva prima di Python 3.x, non possiamo ordinare un dizionario
utilizzando direttamente l’elenco ottenuto dal metodo keys.
Facciamo un esempio supponiamo di voler elencare in ordine alfabetico un dizionario che
rappresenta gli studenti con i rispettivi voti in una materia. Ecco cosa accadrebbe se tentiamo il
vecchio approccio:
>>> diz1 = {'andrea':28, 'giuseppe':25, 'mario':21, 'elena':28}
>>> k = diz1.keys()
>>> k.sort()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'dict_keys' object has no attribute 'sort'
Come workaround possiamo ottenere una vista ordinata convertendo in una lista l’elenco delle
chiavi e applicare a quel punto il metodo sort.
>>> k=list(k) #conversione in lista
>>> k
['mario', 'giuseppe', 'andrea', 'elena']
31
>>> k.sort()
>>> k
['andrea', 'elena', 'giuseppe', 'mario']
>>> for elemento in k: print(elemento, diz1[elemento])
...
andrea 28
elena 28
giuseppe 25
mario 21
32
Tuple
Una tupla in Python è molto simile ad una lista: il suo funzionamento è per lo più il medesimo,
cerchiamo quindi di capire il funzionamento della tupla esaminando le differenze con la lista.
La prima differenza tra tupla e lista è sintattica: le tuple sono racchiuse tra parentesi tonde (e non
quadre come le liste).
Per rappresentare una tupla vuota si usa la seguente sintassi:
>>> t=()
>>> t
()
Mentre per rappresentare una tupla con un elemento si usa la sintassi:
>>> t=(1,)
>>> t
(1,)
La seconda differenza è forse più sottile ma è sostanziale:


La lista è un tipo mutabile
La tupla è un tipo non mutabile
Tipi mutabili
Cerchiamo di chiarire questo concetto di Python: le variabili di tipo mutabile possono cambiare di
stato durante la loro vita, infatti per una lista è possibile aggiungere o togliere elementi in qualsiasi
momento.
Per i tipi non mutabili ciò non è possibile, è possibile solamente cambiare in blocco l’intero valore.
Usare le tuple
Le tuple sono utilizzate quando si deve essere certi che nessuno possa modificare il contenuto
dell’elenco, e quindi non si possa aggiungere o togliere elementi.
Gli operatori sono gli stessi delle liste (a parte quelli che mutano il valore, che chiaramente non
hanno motivo di esistere), vediamo alcuni esempi di indicizzazione e slicing:
>>> tupla=(1,2,3,4)
>>> tupla
(1, 2, 3, 4)
33
>>> tupla[3]
#indicizzazione
4
>>> tupla[1:-1]
#slicing
(2, 3)
Come per le stringhe e per le liste abbiamo gli operatori di concatenazione e ripetizione:
>>> ('primo','secondo')+('terzo','quarto') # concatenazione
('primo', 'secondo', 'terzo', 'quarto')
>>>
('primo',)*2
# ripetizione
('primo', 'primo')
Come accennato in precedenza le tuple a differenza delle liste non possono subire modifiche alla
struttura o al singolo valore:
>>> tupla=(1,2,3)
>>> tupla.append(4)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'append'
>>> tupla.remove(1)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'tuple' object has no attribute 'remove'
>>> tupla[0]=2
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment
34
A cosa servono le tuple?
Le tuple sono più veloci delle liste. Se si vuole un gruppo costante di valori e l'unica cosa che si
intende fare è iterare al suo interno, si definisce una tupla invece di una lista.
Il codice risulta più sicuro “proteggendo dalla scrittura” i dati che non devono essere modificati.
Usare una tupla invece di una lista è come avere un'implicita istruzione assert che mantenga il
dato costante e che richieda una riflessione (ed una specifica funzione) per modificarlo.
Le tuple sono anche usate nelle formattazione delle stringhe.
Le chiavi di un dizionario possono essere interi, stringhe e anche tuple. Le tuple possono essere
usate come chiavi in un dizionario, le liste no. Poiché le chiavi di un dizionario devono essere
immutabili, se si ha una tupla di liste, questa è mutabile e quindi non è sicuro usarla come chiave
di un dizionario. Solo tuple di stringhe, numeri o altre tuple sicure possono essere usate come
chiavi per un dizionario.
Conversione liste-tuple, tuple-liste
È possibile effettuare la conversione da liste a tuple e viceversa in maniera piuttosto semplice, con
le funzioni list e tuple. Vediamo come:
>>> tupla=(1,2,3,4)
>>> lista=list(tupla)
# conversione tupla-lista
>>> lista
[1, 2, 3, 4]
>>> tuplaconv=tuple(lista) # conversione lista-tupla
>>> tuplaconv
(1, 2, 3, 4)
35
I file in Python
Il concetto di file è piuttosto noto. Il fatto che la gestione dei file in Python sia implementata
internamente al linguaggio (built-in), garantisce una notevole velocità e semplicità nella loro
gestione. In particolare è importante poter gestire i file con istruzioni del linguaggio di
programmazione, per salvare delle informazioni sul disco e renderle di conseguenza persistenti.
I file, come tutto in Python, sono oggetti e ad oggetti di tipo file fanno riferimento le operazioni
più comuni, come aprire e chiudere un file, leggere e scrivere in sequenza byte sul medesimo file,
etc. Tutto ciò vale per file di testo e file binari.
Ecco una tabella con le principali funzioni built-in per la gestione dei file:
Operazione
Descrizione
output = open('pippo.txt','w')
apertura di un file in scrittura
input = open('dati','r')
apertura di un file in lettura
s = input.read()
lettura dell’intero contenuto del file
s = input.read(N)
lettura di N bytes
s = input.readline()
lettura di una riga (per files di testo)
s = input.readlines()
restuisce l’intero file come lista di righe (per files di testo)
output.write(s)
scrive nel file i valori passati come parametri e ritorna il
numero di bytes scritti
output.writelines(L)
scrive la lista L in righe nel file
output.close(L)
chiusura del file
Le variabili input e output della tabella sono oggetti di tipo file. Ecco un altro semplice
esempio:
>>> miofile = open('html.txt','w')
>>> miofile.write('riga 1\n')
# apre il file in scrittura
#
scrive riga 1
#
scrive riga 2
#
scrive riga 3
7
>>> miofile.write('riga 2\n')
7
>>> miofile.write('riga 3\n')
36
7
>>> miofile.close()
>>> miofile = open('html.txt','r')
>>> miofile.readlines()
lista di righe
# chiude il file
# apre il file in lettura
#
legge dal file restituisce una
['riga1\n', 'riga2\n', 'riga3\n']
La funzione open apre il file in scrittura e ritorna un oggetto di tipo file che associamo a miofile.
Utilizziamo l’istanza creata per scrivere nel file con il metodo write e lo chiudiamo con close.
Poi riapriamo lo stesso file in lettura e ne stampiamo il contenuto con readlines().
Modalità di apertura di open
Olre a "w" e "r" (scrittura e lettura), che abbiamo già visto, la funzione open consente altre
modalità per l’apertura dei file, che possiamo passarle come secondo parametro:
Modalità
"r"
"w"
"rb" e "wb"
"w+" e "w+b"
"r+" e "r+b"
Descrizione
Apre un file di testo in lettura, equivalente a "rt", se si omette il secondo
parametro di open è la modalità di default
Apre un file in scrittura, e ne azzera i contenuti
Apre un file binario in lettura o scrittura con azzeramento del contenuto
Aprono un file in modifica, rispettivamente testuale e binario, e consentendone
l’aggiornamento, ma ne azzerano i contenuti
Aprono un file in modifica, rispettivamente testuale e binario, e ne consentono
l’aggiornamento senza azzerare i contenuti
Dai file aperti in modalità binaria possiamo estrarre i dati come oggetti byte senza alcuna codifica.
Per sapere tutto sulle modalità di apertura dei file possiamo interrogare Python:
>>> print(open.__doc__)
Muoversi all’interno del file
Come per C o altri linguaggi evoluti anche con Python possiamo spostarci all’interno dei file, ecco
le principali metodi dell’oggetto file:
Metodo
Descrizione
Ritorna la posizione attuale del cursore all’interno del file
seek(pos, rel) Sposta la posizione del cursore all’interno del file, con il primo parametro indichiamo
il numero di byte (positivo o negativo) di cui vogliamo spostarci, il secondo
parametro indica il punto di partenza ( 0=dell’inizio del file; 1=dalla posizione attuale;
2:dalla fine del file)
tell()
37
read(N)
Legge N bytes dalla posizione corrente e sposta il cursore avanti di N posizioni
Infine per verificare lo stato del file è sufficiente stampare i dati dell’istanza corrente. Esempio:
>>> miofile
<_io.TextIOWrapper name='html.txt' mode='r' encoding='cp1252'>
Anche se sembra scontato è utile ricordare di chiudere sempre i file ( close()), dopo averli
utilizzati.
38
Cicli e istruzioni condizionali
In questa lezione vediamo come sono concepiti i classici costrutti condizionali e le iterazioni in
Python e come si utilizzano in pratica.
if-elif-else
Il costrutto if-elif-else permette di eseguire istruzioni o gruppi di istruzioni diverse a seconda del
verificarsi di una condizione:
if condizione1:
<gruppo di istruzioni 1>
elif condizione2:
# opzionale
<gruppo di istruzioni 2>
...
elif condizione(n-1):
# opzionale
<gruppo di istruzioni (n-1)>
else:
# opzionale
<gruppo di istruzioni n>
Le condizioni sono seguite dai due punti ( : ) e il codice che segue deve essere indentato secondo
la convenzione di Python. Possiamo inserire quante condizioni alternative ( elif ) desideriamo e
alla fine una condizione che è alternativa a tutte le altre ( else ), questo comportamento è simile
anche quello dello switch-case-break che troviamo in altri linguaggi come il C.
Trattandosi di condizioni tutte alternative, solo la prima che viene verificata causa l’esecuzione del
codice al suo interno: tutte le successive saranno ignorate anche se verificate.
Per fare un esempio, supponiamo di voler scrivere una semplice lista della spesa e controllare la
quantità di ogni oggetto da comprare, per fare questo utilizziamo un dizionario con valori statici
per semplicità:
spesa={'biscotti':3,'pane':1,'pasta':3,'legumi':1}
>>> spesa
{'biscotti': 2, 'legumi': 1, 'pane': 1, 'pasta': 3}
Adesso cerchiamo il primo dei valori maggiore di 2 in un certo ordine (pasta, biscotti, pane,
legumi).
39
>>> if spesa.get('pasta')>2:
print('Attenzione valore pasta:', spesa.get('pasta')
elif spesa.get('biscotti')>2:
print('Attenzione valore biscotti:', spesa.get('biscotti'))
elif spesa.get('pane')>2:
print('Attenzione valore pane:', spesa.get('pane'))
elif spesa.get('legumi')>2:
print('Attenzione valore legumi:', spesa.get('legumi'))
else:
print('Tutto ok!')
Attenzione valore pasta: 3
Anche la condizione sui biscotti era verificata ma viene ignorata.
Ciclo while
Il ciclo while è il più generico tra i cicli perché non strettamente collegato a variabili, ma ad una
semplice condizione di controllo. Eccone la sintassi in Python:
while condizione:
<gruppo di istruzioni>
Il comportamento prevede l’esecuzione delle istruzioni all’interno de ciclo finché la condizione
rimane verificata. Si esce dal ciclo (o non vi si entra proprio) quando la condizione è falsa.
Ecco un esempio:
>>> a=0
>>> b=10
>>> while a<b:
print(a)
a=a+1
0 1 2 3 4 5 6 7 8 9
40
Ciclo for
Il ciclo for è un’altro dei costrutti più noti e comuni nei linguaggi di programmazione, tipicamente
prevede un contatore che viene incrementato fino al raggiungimento di un certo valore, che
stabilisce l’uscita dal ciclo.
Vediamo come è concepito in Python, ecco la sintassi:
for <contatore del ciclo> in <lista>:
<gruppo di istruzioni>
Il contatore del ciclo è una variabile alla quale viene assegnato, ad ogni passo del ciclo, un valore
della lista. In questo modo all’interno del gruppo di istruzioni è possibile operare sul singolo
elemento della lista.
Vediamo un esempio:
>>> lista = [1,2,3,4]
>>> newLista =[]
>>> for i in lista:
if i>2:
newLista.append(i)
print(newLista)
[]
[]
[3]
[3, 4]
Il costrutto for sembra molto limitato perché, a differenza di altri linguaggi di programmazione,
permette di operare solamente sulle liste. In realtà questa piccola limitazione viene facilmente
superata utilizzando la funzione range.
range
La funzione range permette di costruire una lista di numeri partendo da 0 fino ad un valore
scelto, in questo modo è sufficiente creare la lista da utilizzare nel ciclo for con questa istruzione
per ottenere il medesimo risultato di altri linguaggi di programmazione. Vediamo un esempio che
spiega bene questo trucco:
>>> lista = range(4)
41
>>> for i in lista:
print(i)
0123
Oppure più brevemente:
>>> for i in range(10):
print(i)
0123456789
Se non si vuole cominciare da 0 basta indicare alla funzione range anche il valore iniziale:
>>> for i in range(3,8):
print(i)
3 4 5 6 7
Forzare l’uscita dal ciclo
È sempre possibile forzare l’uscita dal ciclo (qualsiasi ciclo) in ogni momento, grazie ad alcuni
comandi:
Comando
Descrizione
break
permette di saltare fuori da un ciclo ignorando le restanti istruzioni da eseguire
continue
permette di saltare alla prima istruzione della prossima iterazione del ciclo
else
sia il ciclo for che il ciclo while hanno un costrutto aggiuntivo opzionale che permette di
eseguire un blocco di istruzioni all’uscita dal ciclo, queste istruzioni vengono ignorate se
usciamo dal ciclo con un break
Come conseguenza le sintassi dei due cicli si estendono nel seguente modo:
for <contatore-del-ciclo> in <lista>:
<gruppo di istruzioni 1>
else:
<gruppo di istruzioni 2> # non eseguita in caso di break
42
>>> a = 0
>>> b = 10
>>> while a<b
a=a+1
print(a)
if a==5:
break
else:
print('sono uscito regolarmente')
1234
while <test>:
<gruppo di istruzioni 1>
else:
<gruppo di istruzioni 2> # non eseguita in caso di break
Se impostiamo b < 5 vediamo apparire la scritta “sono uscito regolarmente”, altrimenti il break
impedisce l’esecuzione del blocco else del while.
L’istruzione pass
L’istruzione pass è un operazione nulla, quando viene eseguita non succede nulla, è utile come
segnaposto.
Vediamo un semplice esempio
for lettera in 'HTML.it':
if lettera == '.':
pass
# non fa nulla
print('Punto catturato')
continue
print('Lettera attuale: ',lettera)
Lettera attuale:
Lettera attuale:
Lettera attuale:
Lettera attuale:
Punto catturato
Lettera attuale:
Lettera attuale:
H
T
M
L
i
t
43
Comprehension per liste e dizionari
Una comprehension è una modalità di estrazione di sottoinsiemi da liste o dizionari. È molto
potente perché ci permette di agire sugli elementi dell’insieme (lista o dizionario) e filtrarli allo
stesso tempo, come se definissimo in matematica il codominio di una funzione:
insieme = ( f(x) | x appartiene a vecchio insieme, ad una certa condizione )
La sintassi Python per la list-comprehension e dictionary-comprehension risulta molto potente ed
espressiva:
lista = [espressione for variabile in altra_lista if espressione]
diz
= {espr_chiave : espr_valore for espr_chiave, espr_valore in altro_diz if
espressione}
diz = {espr_chiave : espr_valore for variabile in altra_lista if espressione}
Questi strumenti permettono di compiere operazioni iterative su sequenze in maniera più
immediata, flessibile ed efficiente rispetto alle consuete istruzioni cicliche che abbiamo già visto.
Esempi di comprehension
Il modo migliore di comprendere questi strumenti è quello di fare degli esempi. Iniziamo dalla
comprehension per liste e vedremo subito l’eleganza e la potenza nella definizione e creazione
di una lista.
Esempio di conversione euro-dollaro:
>>> euro = [2.5, 3.7, 20.9]
#lista di valori da convertire in dollaro
>>> dollaro = [x*1.3 for x in euro]
>>> dollaro
[3.25, 4.8100000000000005, 27.169999999999998]
>>> dollaroFiltrato=[x*1.3 for x in euro if x>5.0]
>>> dollaroFiltrato
[27.169999999999998]
Vediamo adesso un paio di semplici esempi di comprehension per dizionari, simili a quelli fatti
per le liste.
>>> x=[1,2,3,4]
#data la lista x si vuole incrementare ogni valore di 100
>>> dictComp={y:y+100 for y in x}
44
>>> dictComp
{1: 101, 2: 102, 3: 103, 4: 104}
>>> dictCompFiltrato={y:y+100 for y in x if y>2}
>>> dictCompFiltrato
{3: 103, 4: 104}
45
Funzioni
Le funzioni sono tra le caratteristiche più importanti dei linguaggi di programmazione. In generale
possiamo considerarle come delle scatole nere che:
 prendono in ingresso alcuni parametri (o nessuno);
 compiono una certa elaborazione dei parametri o modificano variabili o oggetti già definiti;
 restiuiscono un risultato dell’elaborazione (non sempre le funzioni in Python restituiscono valori).
Sono quindi uno strumento utile per strutturare il codice in blocchi omogenei dal punto di vista
logico al fine di migliorare la lettura e la manutenzione del sorgente.
Inoltre sono un primo passo verso il riutilizzo del codice, una funzione creata con responsabilità
definite e il necessario livello di genericità, può tornare utile in diversi progetti.
Definire una funzione in Python
La sintassi per definire una funzione è molto semplice:
def nome_funzione(<lista parametri separati da virgola>)
<blocco istruzioni>
return <risultato>
Nel caso in cui non prevediamo che la funzione restituisca dei valori in uscita, omettiamo
semplicemente l’istruzione return:
def nome_funzione(<lista parametri separati da virgola>)
<blocco istruzioni>
Quando non si specifica nessun valore di ritorno, la funzione ritornerà il valore None di default.
Scope
Si devono distinguere le “variabili locali” alle funzioni (quindi utilizzabili solo da esse) e le “variabili
globali“, ossia appartenenti al namespace del modulo (quindi utilizzabili al di fuori della funzione).
Quando si utilizza una variabile, Python cerca prima il nome di quella variabile nel namespace
locale. Se la ricerca non da esito positivo, si prosegue con il namespace globale e solo
successivamente si va a cercare il nome tra le funzioni builtin (cioè quelle predefinite in Python
stesso).
Questo meccanismo permette di utilizzare il valore delle variabili globali, ma di non poterle mai
modificare, in quanto un nuovo assegnamento alla variabile provoca la creazione dello stesso
nome in un namespace nuovo.
46
Passaggio dei parametri
Una volta definita una funzione, possiamo richiamarla semplicemente invocando il suo nome e
passandole i parametri tra parentesi.
Ad esempio, quando si richiama una funzione vengono trasferiti i valori delle variabili ai parametri
delle funzioni, che hanno visibilità locale alla funzione. Questo permette alla funzione di venire a
conoscenza di informazioni proveniente dal blocco chiamante.
Facciamo subito un semplice esempio (con e senza return) creando una funzione che prende
come parametri di ingresso una lista e un numero.
>>> def func(lista, num):
lista.append(10)
num=num+3
return lista, num
>>> x=[1,2]
>>> y=4
>>> func(x,y)
([1, 2, 10], 7)
Esempio senza valori di ritorno:
>>> def func(lista, num):
lista.append(10)
num=num+3
>>> x=[1,2]
>>> y=4
>>> func(x,y)
>>> x,y
([1, 2, 10], 4)
La funzione in entrambe i casi modifica la lista esterna x, mentre non succede nulla alla variabile y,
questo si vede bene confrontando i due risultati: nel primo stampiamo i valori associati alle
variabili che avevamo all’interno della funzione, nel secondo stampiamo l’effetto che la funzione
ha avuto nei confronti delle variabili esterne.
47
In genere nei linguaggi di programmazione esistono due modalità di passaggio dei parametri:


Passaggio per valore: viene trasferita alla funzione solo una copia della variabile, quindi la funzione
non può alterare il valore di quella variabile.
Passaggio per riferimento: viene trasferito il riferimento alla variabile [si potrebbe pensare come
l'indirizzo di una casella in memoria], quindi la funzione può alterare il contenuto cui punta il
riferimento, modificando il valore della variabile esterna alla funzione.
In Python si potrebbe dire che i parametri passati alle funzioni siano sempre trasferiti per
riferimento, ma questa cosa va precisata. Questo si spiega con il fatto che le variabili sono in
realtà delle etichette che si applicano agli oggetti in Python, quindi più vicini al concetto di
riferimento che di variabile.
In termini pratici possiamo rileggere il comportamento del nostro codice in questo modo:
1. assegniamo una etichetta y all’oggetto numero 4
2. chiamando la funzione assegniamo anche l’etichetta num all’oggetto numero 4 (come nei migliori
passaggi per riferimento, ma poi cosa accade? )
3. creiamo un oggetto 3+4 e gli assegnamo l’etichetta num (attenzione, abbiamo spostato
l’etichetta num, ma l’etichetta y non è cambiata)
4. usciamo dalla funzione con l’etichetta y ancora ancorata all’oggetto 4
vediamo che succede alla lista:
1. assegnamo l’etichetta x all’oggetto lista [1,2]
2. nella funzione associamo anche l’etichetta lista all’oggetto lista [1,2]
3. a questo punto chiamiamo il metodo append dell’oggetto lista [1,2] e “accidentalmente” lo
facciamo utilizzando l’etichetta lista. Il metodo modifica l’oggetto, ignorando la questione delle
etichette
4. usciamo dalla funzione con l’etichetta x che punta all’oggetto lista [1,2,10] che è stato
modificato
Questo comportamento differente tra una lista e un oggetto numero, sta anche nel fatto che il
primo è un tipo mutabile e il secondo no:
 le variabili di tipo mutabile possono cambiare di stato durante la loro vita, infatti per una lista è
possibile aggiungere o togliere elementi in qualsiasi momento.
 per i tipi non mutabili ciò non è possibile, è possibile solamente cambiare in blocco l’intero
valore.
Parametri facoltativi
È possibile introdurre dei parametri che hanno la caratteristica di essere facoltativi, essi assumono
un valore prestabilito se non vengono valorizzati. Esaminiamo la sintassi di questo esempio:
>>> def funzione2(a, b=30):
print(a,b)
>>> x=10
48
>>> y=19
>>> funzione2(x)
10 30
>>> funzione2(x,y)
10 19
La funzione denominata funzione2 ha due parametri: a e b. Essa viene invocata due volte: il
risultato della prima chiamata sarà 10, 30, infatti il parametro b, non essendo indicato, assume il
valore 30, il risultato della seconda chiamata sarà 10, 19, come ci si aspetta.
Altri esempi
Vediamo anche come passare in ingresso un insieme di valori e trasformarli in tuple (per mezzo
dell’operatore * ) o in dizionari (con il doppio asterisco ** ) in modo automatico, vediamo come:
>>> def creatupla(*tupla):
print(tupla)
print(type(tupla))
>>> creatupla('uno', 'due', 'tre')
('uno', 'due', 'tre')
<class 'tuple'>
Vediamo i dizionari:
>>> def creadizionario(**dizionario):
print(dizionario)
print(type(dizionario))
>>> creadizionario(primo=1, secondo=2, terzo=3)
{'terzo': 3, 'primo': 1, 'secondo': 2}
<class 'dict'>
49
Moduli
I moduli in Python non sono altro che file che possono contenere funzioni, classi. In altre parole
sono librerie che ci permettono di organizzare meglio i progetti, specie quelli di grandi dimensioni
e di riutilizzare il codice.
I moduli quindi sono dei files di script (files con estensione “ .py“) che possono essere richiamati
da altri programmi Python per riutilizzare le funzioni contenute in essi.
Creare moduli è piuttosto semplice, ma ancor più interessante è conoscere quelli già pronti tra i
moltissimi già a disposizione nell’installazione di Python oppure cercare quelli che si trovano
online, messi a disposizione da terze parti.
In “bundle” con Python abbiamo moduli che forniscono funzioni utili per risolvere diverse
problematiche, come:





gestione delle stringhe,
chiamate alle funzioni del sistema operativo,
gestione di internet,
posta elettronica,
…
Online si trovano numerosissime librerie scritte da terzi per risolvere i problemi più disparati e
molte di esse, in pieno stile open source, sono di utilizzo gratuito e sotto licenza GPL.
Scrivere e importare un modulo
Per scrivere un modulo, basta semplicemente creare un file con estensione .py e inserirvi tutte le
funzioni necessarie.
Per utilizzare il modulo appena creato è sufficiente importarlo con il comando import. Ad
esempio, supponendo di voler utilizzare il modulo libreria.py, sarà sufficiente scrivere in cima al
programma:
import libreria
Dopo aver importato il modulo possiamo semplicemente richiamare le funzioni contenute in esso
utilizzando la dot notation. Digitando il nome del modulo, un punto e il nome della funzione
riusciamo ad entrare nel modulo e richiamare la funzione desiderata.
Ad esempio, supponendo che “libreria.py” contenga le funzioni apri(),
sposta(oggetto), possiamo richiamare le funzioni nel seguente modo:
libreria.apri()
ogg=5
libreria.sposta(ogg)
libreria.chiudi()
50
chiudi() e
Se non si desidera utilizzare il nome della libreria tutte le volte che si richiama una funzione, è
possibile importare anche i nomi delle funzioni direttamente. Ad esempio, per importare la
funzione sposta(oggetto):
import libreria
from libreria import sposta
libreria.apri()
ogg=5
sposta(ogg)
libreria.chiudi()
In questo caso la funzione sposta viene a far parte dell’insieme dei nomi definiti nel programma
(namespace), e non necessita più del prefisso del nome del modulo (libreria).
Se si desidera importare tutti i nomi delle funzioni di “libreria.py” all’interno del programma basta
utilizzare il carattere asterisco ( * ):
from libreria import *
apri()
ogg=5
sposta(ogg)
chiudi()
Compilazione ottimizzata dei moduli
Bisogna considerare un altro vantaggio offerto dai moduli: quando si interpreta un programma
Python, esso crea per ogni modulo una versione “semicompilata” in un linguaggio intermedio
(bytecode).
Dopo una esecuzione, è possibile notare la presenza di tanti file con estensione .pyc (Python
compiled). Ogni file ha lo stesso nome del relativo sorgente .py.
In questo modo Python non dovrà interpretare tutto il codice tutte le volte, ma solamente quando
viene effettuata una modifica. L’interprete confronta ogni volta la data e l’ora del file .py con il
file .pyc: se sono diverse interpreta il codice, altrimenti esegue direttamente il bytecode.
I moduli standard
Python è dotato di una raccolta di moduli standard molto vasta. Per utilizzare tali moduli è
sufficiente importarli come abbiamo visto in precedenza. Vediamo alcuni moduli di notevole
importanza:
51
modulo
string.py
sys.py
descrizione
per gestire le stringhe, ad esempio:
o funzioni per la conversione da stringa a numero
o funzioni per la conversione da minuscolo a maiuscolo
o funzioni per la sostituzioni di pezzi di stringhe
per reperire informazioni di sistema, ad esempio reperire gli argomenti passati
sulla linea di comando
os.py
per eseguire operazioni del sistema operativo sottostante, ad esempio copiare,
rinominare o cancellare un file
graphics.py
per funzioni di grafica elementare
Nella documentazione inclusa con Python si trova l’elenco completo di tutti i moduli predefiniti.
Namespaces
Per meglio comprendere il meccanismo dell’importazione dei nomi delle funzione bisogna parlare
del concetto di namespace (termine già introdotto in precedenza): ogni modulo ha un insieme di
nomi (nomi di variabili e di funzioni) che rappresentano i nomi utilizzabili al suo interno. Questo
insieme viene detto namespace (spazio dei nomi).
Per trasportare i nomi da un namespace ad un altro si può usare il comando import che abbiamo
visto.
Grazie alla funzione dir() è possibile visualizzare l’elenco dei nomi presenti nel namespace
corrente.
>>> dir()
['__builtins__', '__doc__', '__name__']
Questi nomi, mostrati sopra, sono nomi definiti dall’interprete prima di cominciare. Se io importo
il modulo libreria ottengo il seguente risultato:
>>> from libreria import *
>>> dir()
['__builtins__', '__doc__', '__name__', 'apri', 'chiudi', 'sposta']
Come si intuisce, adesso tutte le funzioni contenute in libreria.py fanno parte del namespace
corrente.
52
Il concetto di namespace si applica anche alle funzioni, quando si entra in una funzione viene
creato un nuovo namespace, ecco perché non sono più visibili le variabili precedenti, ma solo le
variabili locali alla funzione stessa.
Infine vediamo altre due funzioni built-in: locals() e globals()
>>> locals()
{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__doc_
_': None, '__package__': None}
>>> globals()
{'__builtins__': <module 'builtins' (built-in)>, '__name__': '__main__', '__doc_
_': None, '__package__': None}
Entrambe ritornano un dizionario, ma proviamo adesso ad importare un modulo:
>>> import math
>>> globals()
{'__builtins__': <module 'builtins'="" (built-in)="">, '__name__': '__main__',
'__doc_
_': None, 'math': <module 'math'="" (built-in)="">, '__package__': None}
>>> locals()
{'__builtins__': <module 'builtins'="" (built-in)="">, '__name__': '__main__',
'__doc_
_': None, 'math': <module 'math'="" (built-in)="">, '__package__': None}
</module></module></module></module>
Come è possibile vedere il namespace globals e locals continuano ad essere equivalenti,
ma con il nuovo modulo importato.
53
Gestione delle eccezioni
Il momento peggiore per un programmatore è rappresentato dal blocco del programma a causa di
un errore.
Esistono due tipi di errori:


Errori sintattici: dovuti all’errata scrittura del nome di un comando o di una funzione.
Errori di runtime: dovuti al verificarsi di una condizione imprevista durante l’esecuzione
(es. divisione per zero, lettura di file inesistenti, ... )
Quando si ha un errore, il programma si ferma e viene evidenziato un messaggio di errore. Questo
evento provoca una brusca interruzione del flusso di controllo del programma, quindi non è più
possibile mantenere in vita il programma. In realtà, ciò risulta vero per gli errori sintattici, per i
quali l’interprete Python non sa cosa deve eseguire, ma non è completamente vero per gli errori
runtime.
Nel seguente esempio si ha un errore di runtime, in questo caso si dice che si è verificata una
eccezione, ossia un evento accidentale (in realtà in questo esempio un po’ forzato …):
>>> a, b = 5, 0
>>> print a / b
traceback (most recent call last):
File “<pyshell#5>”, line 1, in ?
print a / b
ZeroDivisionError: integer division or modulo by zero
è possibile controllare questi eventi accidentali senza terminare il programma, per fare questo si
utilizza un costrutto che permette di rilevare le eccezioni e passare il controllo di flusso ad un altro
blocco di istruzioni:
try:
<gruppo di istruzioni sotto test>
except:
<gruppo di istruzioni da eseguire in caso di errore>
else: # opzionale
<gruppo di istruzioni2>
finally: # opzionale, al posto di except
<gruppo di istruzioni3>
Tutte le istruzioni incluse nel blocco try sono tenute sotto controllo durante l’esecuzione del
programma. Se tutto va bene il blocco except viene ignorato. In caso contrario, se avviene una
eccezione, si salta al blocco di istruzione che seguono la parola except.
Se incapsuliamo ogni operazione a rischio di eccezioni in un blocco try siamo in grado di reagire ad
ogni errore runtime senza interrompere il programma.
54
Tornando all’esempio procedente si può operare in questo modo:
>>> a, b = 5, 0
>>> try:
print a / b
except:
print ‘tentativo di divisione per zero !’
Tentativo di di divisione per zero !
è possibile anche gestire tipologie diverse di eccezioni contemporaneamente, ed eseguire blocchi
di istruzioni diverse a seconda del tipo di errore.
Per permettere questo è necessario fare seguire alla parola except il nome della classe di errore.
Tale nome è rilevabile ad esempio dal messaggio Python in caso di eccezione.
Riportando il solito esempio, per gestire in modo più puntuale l’eccezione avremo potuto scrivere
nel seguente modo:
>>> a, b = 5, 0
>>> try:
print a / b
except ZeroDivisionError:
print ‘tentativo di divisione per zero !’
Tentativo di di divisione per zero !
Nel caso si verificasse una eccezione non legata alla divisione per zero si verificherebbe
ugualmente un blocco del programma, anche in presenza del blocco try.
 Se si desidera eseguire un particolare gruppo di istruzioni solo nel caso in cui non avvenga
nessuna eccezione, basta inserire la parola chiave else, seguito dal blocco di istruzioni
desiderate.
 Se si desidera far eseguire ugualmente il blocco except anche in caso di nessuna eccezione, è
sufficiente sostituire la parola chiave except con la parola chiave finally.
Una nota finale per chi volesse approfondire l’aspetto di gestione delle eccezioni di Python:
è possibile creare delle classi di eccezioni personalizzate, le quali possono essere generate in un
punto qualsiasi utilizzando il comando raise.
55
Classi e cenni di programmazione ad oggetti
Nei capitoli introduttivi abbiamo detto che Python è un linguaggio orientato agli oggetti. In realtà
esso permette sia la programmazione tradizionale (procedurale) che il nuovo paradigma ad
oggetti. Quindi Python si inquadra nei linguaggi ibridi, come il C++.
In questo capitolo cercheremo di introdurre teoricamente i concetti della programmazione
orientata agli oggetti, accompagnando ogni concetto con qualche piccolo esempio. Solo in seguito
trasferiremo i concetti teorici in Python, illustrando la sintassi necessaria all’utilizzo degli oggetti in
Python stesso.
La programmazione tradizionale si è sempre basata sull’utilizzo di strutture dati (come le liste, le
tuple, … ) e su funzioni e procedure (tutti concetti già visti in precedenza).
Questo metodo di sviluppo del software viene detto funzionale (o procedurale), con esso si
organizza un intero programma in moduli che raccolgono gruppi di funzioni. Ogni funzione accede
ad uno o più gruppi di dati.
I metodi di sviluppo funzionale hanno però notevoli debolezze:


A causa dei stretti legami tra le funzioni e i dati, si arriva ad un punto in cui ogni modifica software
provoca degli effetti collaterali su altri moduli con enormi difficoltà di debug dell’applicazione.
Difficoltà di riutilizzo del software. Ogni volta che si vuole riciclare una funzione bisogna apportare
delle modifiche strutturali per adeguarla alla nuova applicazione.
La programmazione orientata agli oggetti è un modo alternativo di scomposizione di un progetto
software: in essa l’unità elementare di scomposizione non è più l’operazione (la procedura) ma
l’oggetto, inteso come modello di un’entità reale (un oggetto del mondo reale).
Questo approccio porta ad un modo nuovo di concepire un programma: il software è ora
costituito da un insieme di entità (gli oggetti) interagenti, ciascuna provvista di una struttura dati e
dell’insieme di operazioni che l’oggetto è in grado di effettuare su quella struttura. Poiché ciascun
oggetto incapsula i propri dati e ne difende l’accesso diretto da parte del mondo esterno, si è certi
che cambiamenti del mondo esterno non influenzeranno l’oggetto o il suo comportamento.
D’altra parte per utilizzare un oggetto basta conoscere che dati esso immagazzina e che operazioni
esso fornisce per operare su questi dati, senza curarsi dell’effettiva realizzazione interna
dell’oggetto stesso.
Questo nuovo modo di sviluppare programmi software è più vicino alla nostra realtà quotidiana.
Pensiamo ad un oggetto del mondo reale, ad esempio una automobile. Una automobile ha un
insieme di caratteristiche: il colore , la cilindrata ecc... Inoltre essa dispone di operazioni da
svolgere esclusivamente con essa, ad esempio:



accensione.
cambio della marcia.
parcheggio.
è giusto correlare le sue caratteristiche e le sue operazioni in una sola entità (un solo oggetto).
Inoltre la programmazione ad oggetti favorisce la programmazione di gruppo, poiché gli oggetti
non possono dipendere dall’implementazione di altri oggetti, ma solo dalle loro operazioni, perciò
56
un programmatore può sviluppare un oggetto senza preoccuparsi della struttura degli altri
elementi che compongono il sistema.
Vediamo ora i principali concetti su cui si basa questo modo di programmare:
Una classe definisce un tipo di oggetto. Se intendo creare un nuovo oggetto ( istanza ) devo
indicare al programma le sue caratteristiche.
In particolare la classe definisce:


Le variabili contenute nell’oggetto, dette dati membri (o proprietà)
Le funzioni contenute nell’oggetto, dette metodi. Queste funzioni permettono di svolgere
operazioni solo sui dati membri dell’oggetto stesso. Ogni metodo agisce esclusivamente sui dati
membri della classe di appartenenza. Questo vincolo rappresenta la grande forza della
programmazione ad oggetti, la quale costringe il programmatore ad organizzare il software per
componenti riciclabili ben distinti.
Ad esempio, se volessi costruire un programma che conserva un archivio di persone, potrei creare
la classe “PERSONA“.
Tale classe potrebbe avere i seguenti dati membri:





nome della persona
cognome della persona
indirizzo
telefono
stato civile
Inoltre si potrebbero definire i seguenti metodi:



cambia l’indirizzo della persona
cambia il telefono della persona
cambia lo stato civile della persona
Questi metodi agiscono esclusivamente sui dati membri della classe.
57
Una volta definita una classe, siamo in grado di creare tanti oggetti distinti caratterizzati da
differenti valori delle caratteristiche della classe stessa.
Gli oggetti non sono altro che “istanze” della classe. Tornando al nostro esempio delle persone,
possiamo creare i seguenti oggetti:



Stefano Riccio
Rossi Mario
Elena Bianchi
Queste sono tre istanze della classe persona. Ogni oggetto ha una copia dei dati membri dove
conserva tutte le proprie informazioni.
La definizione di classe permette di realizzare l’incapsulamento. Esso consiste nella protezione dei
dati membri dagli accessi non desiderati.
Questo avviene perché dall’esterno di un oggetto si può accedere ad un dato membro solo
mediante un metodo e non direttamente usando il nome del dato membro stesso.
Ad esempio, se volessi modificare l’indirizzo di una persona non posso semplicemente assegnare il
nuovo indirizzo al nome della variabile (dato membro), come si farebbe nella programmazione
tradizionale, ma sono obbligato ad utilizzare l’apposito metodo.
In realtà l’incapsulamento non è obbligatorio. Si può decidere, singolarmente su ogni dato
membro, se renderlo protetto oppure no.
Generalmente gli oggetti hanno un insieme di metodi e dati che sono resi di dominio pubblico,
mentre altri sono inaccessibili dall’esterno. Questo principio è conosciuto con il nome di
“information hiding” (mascheramento dell’informazione) e fa si che un oggetto sia diviso in due
parti ben distinte: una interfaccia pubblica e una rappresentazione privata.
Il mascheramento dell’informazione permette di rimuovere dal campo di visibilità esterno
all’oggetto alcuni metodi o dati che sono stati incapsulati nell’oggetto stesso. L’incapsulamento e il
mascheramento dell’informazione lavorano insieme per isolare una parte del programma o del
sistema dalle altre parti, permettendo così al codice di essere modificato ed esteso senza il rischio
di introdurre indesiderati effetti collaterali.
Questo metodo risulta molto utile per costruire librerie software da rilasciare a terze parti. Infatti,
chi utilizza la libreria vede solamente l’interfaccia pubblica e ignora tutto il resto.
58
Un altro concetto importantissimo della programmazione ad oggetti e l’ereditarietà.
Con essa è possibile definire una classe sfruttando le caratteristiche di un’altra classe (che diventa
la classe madre).
Ad esempio, se volessimo creare la classe degli studenti, dovremmo costruire una classe simile a
quella delle persone, con l’aggiunta di qualche informazione in più.
PERSONA
STUDENTE
Per evitare di scrivere tutto nuovamente, posso indicare al programma di ereditare tutte le
caratteristiche dalla classe “persona” e aggiungere alcuni dati membri e alcuni metodi.
In questo modo posso affermare che gli studenti sono delle persone, quindi ereditano da essi le
loro caratteristiche. Inoltre posso aggiungere ad esempio i seguenti dati membri specifici degli
studenti:


scuola di appartenza
classe di appartenza
Inoltre si potrebbero definire i seguenti metodi specifici della classe studenti:


cambia scuola
promosso
L’ereditarietà permette di utilizzare anche i metodi delle classi progenitrici, cosi per cambiare il
nome di uno studente posso semplicemente utilizzare il metodo apposito della classe persona.
Un metodo, in una classe discendente, può nascondere la visibilità di un metodo di una classe
antenata, semplicemente definendo il metodo con lo stesso nome. Lo stesso nome può così essere
utilizzato in modo appropriato per oggetti che sono istanze di classi diverse. Ereditando dalle classi
antenate i metodi che operano correttamente anche nelle classi discendenti, ed eliminando quei
metodi che devono agire in modo differente, il programmatore estende realmente una classe
antenata senza doverla completamente ricreare.
La forma più comune di creazione di una classe è la specializzazione, mediante la quale viene
creata una nuova classe poiché quella esistente è troppo generica. In questo caso è possibile
utilizzare il meccanismo dell’ereditarietà singola. Questo è il caso dell’esempio proposto delle
persone e degli studenti.
Un altro tipico metodo di creazione è la combinazione con la quale la nuova classe è creata
combinando gli oggetti di altre classi. In questo caso, se esiste, si utilizza il meccanismo
dell’ereditarietà multipla.
59
Per porre in relazione gli oggetti, sono quindi utilizzati due tipi di ereditarietà: quella singola e
quella multipla. Attraverso l’ereditarietà singola, una sottoclasse può ereditare i dati membri ed i
metodi da un’unica classe, mentre con l’ereditarietà multipla una sottoclasse può ereditare da più
di una classe.
L’ereditarietà singola procura i mezzi per estendere o per perfezionare le classi, mentre
l’ereditarietà multipla fornisce in più i mezzi per combinare o unire classi diverse.
Le opinioni riguardo la necessità o meno del meccanismo dell’ereditarietà multipla sono piuttosto
controverse.
I contrari sostengono che si tratta di un meccanismo non strettamente necessario, piuttosto
complesso e difficile da utilizzare correttamente. Quelli a favore dicono esattamente l’opposto ed
infatti sostengono che l’ereditarietà multipla è una caratteristica fondamentale di un linguaggio
object oriented.
L’ereditarietà multipla incrementa sicuramente le capacità espressive di un linguaggio, ma
comporta un costo elevato in termini di complessità della sintassi e di overhead di compilazione e
di esecuzione e, in definitiva, risulta di scarso utilizzo pratico.
I linguaggi object-oriented permettono la creazione di gerarchie di oggetti (mediante
l’ereditarietà) cui sono associati metodi che hanno lo stesso nome, per operazioni che sono
concettualmente simili ma che sono implementate in modo diverso per ogni classe della gerarchia.
Di conseguenza, la stessa funzione richiamata su oggetti diversi, può causare effetti
completamente differenti. Questa funzionalità viene chiamata polimorfismo.
Un caso molto interessante di polimorfismo è rappresentato dall’overloading degli operatori. Con
questa tecnica è possibile definire degli operatori matematici sugli oggetti che permettono di
compiere operazioni sulle istanze in base al tipo di oggetto con il quale lavorano.
Approfondiremo questo aspetto in seguito.
60
Classi in Python
Ecco di seguito la sintassi da utilizzare per definire una classe in Python:
class <nome classe> [(<classe madre>,...)]:
<elenco dati membro da inizializzare>
<elenco metodi>
I dati membro si esprimono come le normali variabili di Python. Se devo inizializzare dei dati
membro faccio un semplice assegnamento, altrimenti posso definirli al momento dell’utilizzo,
esattamente come avviene per le variabili normali.
Per i metodi basta utilizzare la medesima sintassi delle funzioni con alcuni accorgimenti.
Ogni metodo deve avere come primo parametro l’oggetto stesso, infatti ogni volta che viene
richiamato il metodo, Python sistema nel primo parametro il riferimento all’oggetto stesso.
Questo permette di accedere ai dati membri appartenenti allo stesso oggetto, normalmente si usa
chiamare questo parametro “self“.
Vediamo l’esempio delle persone scritto praticamente in codice Python:
class persona:
nome = ''
cognome = ''
indirizzo = ''
telefono = ''
stato_civile = ''
def cambia_indirizzo(self,s):
self.indirizzo = s
def cambia_telefono(self,s):
self.telefono = s
def cambia_stato_civile(self,s):
self.stato_civile = s
def stampa(self):
print (self.nome,self.cognome,self.indirizzo,self.stato_civile)
class studente (persona): # ereditarietà
scuola = ''
classe = 0
def cambia_scuola(self,s):
self.scuola = s
def promosso(self):
if self.classe == 5:
print ('scuola finita')
else:
self.classe = self.classe + 1
Se si vuole istanziare un oggetto, è sufficiente richiamare il nome della classe come se fosse una
funzione. Per accedere ai dati membri e ai metodi basta utilizzare il punto.
61
p1 = persona() # le parentesi sono obbligatorie
p1.nome = 'Pico' # assegnazione diretta ai dati membri
p1.cognome = 'De Paperis'
p1.cambia_indirizzo('via dei ciclamini n. 12')
#richiamo un metodo
p1 è un oggetto della classe persona che contiene quei valori.
Si noti come l’assegnazione dei valori ai dati membri venga effettuata direttamente oppure
attraverso gli appositi metodi.
L’utilizzo del metodo cambia_indirizzo passando un solo parametro (il metodo ne chiede due)
è reso possibile perché Python associa al parametro self l’oggetto p1. Utilizzando self si può
accedere direttamente ai dati membro all’interno della classe.
Per istanziare un oggetto di tipo studente, è possibile utilizzare gli stessi dati membri e metodi
della classe progenitrice:
s1 = studente()
s1.nome = 'mario'
s1.cognome = 'rossi'
s1.cambia_indirizzo('via html n. 10')
s1.cambia_scuola('liceo')
s1.stampa() # risultato : mario rossi via html n. 10
Il risultato del metodo “stampa” non permette di visualizzare la scuola e la classe di appartenenza.
Questo avviene poiché viene richiamato il metodo della classe “persona” (classe madre), la quale
non può conoscere il valore dei dati membri della classe “studente” (classe figlia).
Per risolvere questo problema ci viene in aiuto il polimorfismo, infatti è necessario ridefinire il
metodo stampa costruendone una versione specifica per gli studenti.
Riscrivo la classe studente in questo modo:
class studente (persona):
scuola = ''
classe = 0
def cambia_scuola(self,s):
self.scuola = s
def promosso(self):
if self.classe == 5:
print ('scuola finita')
else:
self.classe = self.classe + 1
def stampa(self):
print self.nome,self.cognome,self.indirizzo,self.stato_civile
print 'scuola: '+self.scuola+' classe '+str(self.classe)
62
Il metodo stampa è polimorfico, sembra una brutta parola, ma questo significa che assume una
forma diversa in base al tipo di oggetto sul quale viene applicato.
Spesso è necessario inizializzare i dati membri dell’oggetto nel momento della creazione
dell’istanza dell’oggetto stesso. Nel nostro esempio è utile inizializzare subito la persona con il suo
nome e cognome (infatti il nome e cognome sono assegnati alla nascita e non cambiano più).
Per fare questo la teoria della programmazione orientata agli oggetti prevede l’uso di una funzione
costruttore. In Python esiste qualcosa di simile: è la funzione denominata “__init__()”.
Quando all’interno di una classe viene dichiarata una funzione con questo nome, allora essa viene
invocata automaticamente alla creazione dell’oggetto. Vediamo come modificare la classe
“persona” per inizializzare automaticamente il nome e il cognome:
class persona:
indirizzo = ''
telefono = ''
stato_civile = ''
def __init__(self,n,c):
self.nome = n
self.cognome = c
def cambia_indirizzo(self,s):
self.indirizzo = s
def cambia_telefono(self,s):
self.telefono = s
def cambia_stato_civile(self,s):
self.stato_civile = s
def stampa(self):
print (self.nome,self.cognome,self.indirizzo,self.stato_civile)
Con la chiamata:
p1 = persona('Paolino','Paperino')
p1.stampa() # risultato : Paolino Paperino
Si ottiene l’inizializzazione dei due dati membri. Da notare che non è stata eliminata l’assegnazione
della stringa vuota alle due variabili nome e cognome nella classe: esse infatti vengono
direttamente create all’interno della funzione __init__.
In precedenza abbiamo parlato di incapsulamento e subito dopo non abbiamo applicato questo
principio. Infatti la prima operazione fatta sull’oggetto p1 è stata quella di inizializzare i dati
membri nome e cognome direttamente.
63
Python assume che tutti i dati membri siano pubblici e quindi modificabili dall’esterno
dell’oggetto. Per indicare a Python di tenere protetti i dati membri, e quindi realizzare veramente
l’incapsulamento, si devono anteporre 2 underscore al nome della variabile (“__”).
Cosi facendo nessuno può modificare il dato senza utilizzare l’apposita funzione.
Ad esempio, nella classe “persona” volendo proteggere tutti i dati membri:
class persona:
__indirizzo = ''
__telefono = ''
__stato_civile = ''
def __init__(self,n,c):
self.__nome = n
self.__cognome = c
def cambia_indirizzo(self,s):
self.__indirizzo = s
def cambia_telefono(self,s):
self.__telefono = s
def cambia_stato_civile(self,s):
self.__stato_civile = s
def stampa(self):
print (self.__nome,self.__cognome,self.__indirizzo,
self.__stato_civile)
Se tento di assegnare direttamente “__nome” o “__cognome” il comando viene ignorato:
p1.__nome = 'prova'
p1.stampa() # il risultato rimane quello dell’ultima assegnazione
Esiste un altro concetto della programmazione orientata agli oggetti molto interessante:
la possibilità di effettuare il polimorfismo anche degli operatori, oltre che dei metodi.
Supponiamo di creare la classe dei numeri complessi nel seguente modo:
class numero_complesso:
parte_reale = 0
parte_imm = 0
def somma(self,num):
# num è un oggetto di classe numero_complesso
self.parte_reale = self.parte_reale + num.parte_reale
self.parte_imm = self.parte_imm + num.parte_imm
def stampa(self):
print (str(self.parte_reale) + '+' + str(self.parte_imm)+ 'i')
64
Un oggetto di classe numero_complesso è composto da due valori: la parte reale e la parte
immaginaria e possiede un metodo per eseguire la somma con un altro oggetto della stessa classe.
Per utilizzare questa classe devo scrivere il seguente programma:
n1 = numero_complesso()
n1.parte_reale = 1
n1.parte_immaginaria = 1
n2 = numero_complesso()
n2.parte_reale = 2
n2.parte_immaginaria = 3
n1.somma(n2)
n1.stampa() # risultato 3+4i
La sintassi, purtroppo, risulta piuttosto articolata: sarebbe molto più intuitivo e pratico poter
scrivere n1 + n2, proprio come si fa in matematica.
Per poter scrivere questo è necessario rendere l’operatore “+” di Python polimorfico, in modo che
si accorga di lavorare con i numeri complessi e richiami la giusta funzione.
Per fare questo si deve dichiarare la classe nel seguente modo:
class numero_complesso:
parte_reale = 0
parte_imm = 0
def __add__(self,num):
ris=numero_complesso()
ris.parte_reale = self.parte_reale + num.parte_reale
ris.parte_imm = self.parte_imm + num.parte_imm
return ris
def stampa(self):
print (str(self.parte_reale) + '+' + str(self.parte_imm)+ 'i')
La dichiarazione della funzione speciale “__add__” effettua l’overloading (la sostituzione)
dell’operatore ADD (+), creando al suo interno un nuovo oggetto ed eseguendo somma delle
singole variabili. Vediamo la nuova sintassi di chiamata della funzione:
n1 = numero_complesso()
n1.parte_reale = 1
n1.parte_immaginaria = 1
n2 = numero_complesso()
n2.parte_reale = 2
n2.parte_immaginaria = 3
r=n1+n2
# come in matematica
n1.stampa() # risultato 3+4i
65
Attraverso l’overloading degli operatori si possono creare classi molto sofisticate utilizzabili con
una sintassi veramente molto elegante.
Si riporta di seguito una tabella con alcune funzioni speciali con le quali è possibile effettuare
l’overloading:
Metodi speciali
Descrizione
Esempio
__init__
costruttore oggetto
P1=persona()
__add__
operatore di somma
n1+n2
__or__
operatore OR
x ¦y
__len__
lunghezza
len(x)
__cmp__
confronto
x==y
I sorgenti Python sono raggruppati in moduli. Anche i moduli, come le classi, sono uno strumento
per organizzare bene un programma e ottenere una componentistica da riutilizzare in futuro.
Si pone il problema di come organizzare le classi nei moduli: benché sia possibile inserire più classi
nello stesso modulo, si consiglia di utilizzare un modulo per ogni classe.
In questo modo i singoli file sul disco equivalgono alle classi implementate e si ottiene un miglior
ordine del programma.
Una considerazione finale prima di concludere l’argomento della programmazione ad oggetti.
è difficile esaurire l’argomento della programmazione ad oggetti, poiché esso è molto vasto e
articolato. Bisogna tenere in considerazione che ancora oggi è difficile programmare bene ad
oggetti per diversi motivi:



Ogni linguaggio di programmazione, compreso Python, implementa in modo diverso e solo in parte
le linee teoriche della programmazione ad oggetti.
La maggior parte dei linguaggi sono ibridi e quindi non obbligano il programmatore ad usare
correttamente gli oggetti.
Non è semplice modellare un problema della vita reale ad oggetti per trasformalo in un
programma.
Python è un linguaggio ibrido, e quindi lascia libero il programmatore di scegliere se utilizzare o
meno gli oggetti. Questo potrebbe essere un punto a sfavore di Python rispetto ad altri linguaggio
object orientd puri, come java per esempio.
66
APPENDICE
Colorconsole
Colorconsole è un modulo per la gestione della modalità testo in applicazioni console per Windows, Linux
and Mac OS X.
!
Lo script deve essere eseguito dalla console di Windows (previa impostazione del percorso
dell’interprete python.exe nella variabile d’ambiente path)
Installazione
 Copiare la cartella colorconsole in App\Lib
 Testarne il funzionamento con:
import colorconsole.terminal
colorconsole.terminal.test()
Tabella colori
Numero
0
1
2
3
4
5
6
7
Colore
Black
Blue
Green
Cyan
Red
Purple
Brown
Light grey
Numero
8
9
10
11
12
13
14
15
Colore
Dark grey
Light blue
Light Green
Light Cyan
Light Red
Light Purple
Yellow
White
Metodi dell’oggetto terminal
Al momento sono supportati i terminali Windows e Ansi.
Metodo
set_color(fg = None, bk = None)
set_title(titolo)
cprint(fg, bg, testo)
print_at(x,y, testo)
clear()
gotoXY(x,y)
reset()
columns()
lines()
Descrizione
Imposta i colori di primo piano(fg) e di sfondo (bg)
Imposta il titolo della finestra console
Stampa un messaggio con i colori di testo (fg) e sfondo (bg)
specificati. Equivale all’utilizzo congiunto di set_color e
print
Stampa il testo alle coordinate x,y
Cancella lo schermo utilizzando il colore di sfondo corrente.
Non reimposta la posizione del cursore a (0,0)
Imposta la posizione del cursore alla colonna x e alla riga y
Resetta tutti gli attributi di colore
Ritorna il numero di colonne della finestra di console
corrente
Ritorna il numero di righe della finestra di console corrente
67
La grafica
Esistono varie librerie di grafica, ma una delle più semplici e intuitive per programmare con le funzioni
grafiche fondamentali , è graphics.py
La libreria consente la creazione di finestre (GraphWin) su cui è possibile disegnare tutta una serie di
oggetti grafici elementari (punti, linee, cerchi, rettangoli, ovali, poligoni, testo, immagini) .
Ecco un semplice esempio:
from graphics import *
def main():
win = GraphWin("My Circle", 100, 100)
c = Circle(Point(50,50), 10)
c.draw(win)
win.getMouse() # attesa click nella finestra
win.close()
main()
GraphWin
In un programma si può specificare un qualsiasi numero di finestre grafiche
Metodo
GraphWin(titolo, largh, alt)
plot(x, y, colore)
plotPixel(x, y, Color)
setBackground(color)
close()
getMouse()
checkMouse()
setCoords(xbs, ybs, xad, yad)
68
Descrizione
Crea una nuova finestra. I parametri sono opzionali.
( default: Graphic Window, 200, 200 )
Disegna un pixel alle coordinate x e y col colore specificato.
Il colore è opzionale ( default: nero )
Disegna un pixel ignorando le trasformazioni di coordinate
Imposta il colore di sfondo della finestra.
( default: grigio )
Chiude la finestra
Attesa di click del mouse all’interno della finestra. Le
coordinate vengono restituite come oggetto Point
Simile al precedente, senza attesa. Restituisce l’ultimo
punto di click o None se non vi sono stati click dall’ultima
chiamata di checkMouse o getMouse.
Imposta il sistema di coordinate della finestra (angolo
basso-sinistro, angolo alto-destro). Tutti i successivi
tracciamenti seguono il nuovo sistema di coordinate (ad
eccezione di plotPixel).
Oggetti grafici
La libreria implementa le seguenti classi di oggetti grafici:







Point
Line
Circle
Oval
Rectangle
Polygon
Text
Tutti gli oggetti sono creati inizialmente vuoti, con colore del tratto nero e supportano i seguenti metodi
generici:
Metodo
setFill(colore)
setOutline(colore)
setWidth(pixel)
draw(finestra)
undraw()
move(dx,dy)
clone()
Descrizione
Imposta il colore dell’area interna dell’oggetto al colore
specificato
Imposta il colore del contorno dell’oggetto al colore
specificato.
Imposta lo spessore del contorno al numero di pixel
specificato (non applicabile per l’oggetto Point)
Disegna l’oggetto nella finestra specificata
Cancella l’oggetto dalla finestra specificata. Causa errore
per oggetti non disegnati.
Sposta l’oggetto di dx unità in direzione x e di dy unità in
direzione y. Se l’oggetto è già tracciato, l’immagine viene
aggiornata alla nuova posizione
Restituisce una copia non visibile dell’oggetto
L’oggetto Point
Metodo
Point(x,y)
getX()
getY()
Descrizione
Costruisce un punto alle coordinate specificate
Restituisce la coordinata x di un punto
Restituisce la coordinata y di un punto
L’oggetto Line
Metodo
Line(punto1,punto2)
setArrow(punta)
getCenter()
getP1(), getP2()
Descrizione
Costruisce un segmento fra i due punti specificati
Imposta una freccia con punte assegnate. Possibili valori di
punta: 'first', 'last', 'both', e 'none' ( default:
'none' )
Restituisce una copia del punto medio del segmento
Restituisce una copia degli estremi del segmento
69
L’oggetto Circle
Metodo
Circle(centro,raggio)
getCenter()
getRadius()
getP1(), getP2()
Descrizione
Costruisce un cerchio con centro e raggio assegnati
Restituisce una copia del centro del cerchio
Restituisce il raggio del cerchio
Restituisce una copia dei vertici del quadrato circoscritto
L’oggetto Rectangle
Metodo
Rectangle(punto1,punto2)
getCenter()
getP1(), getP2()
Descrizione
Costruisce un rettangolo con vertici opposti nei punti
assegnati
Restituisce una copia del punto centrale del rettangolo
Restituisce una copia dei punti utilizzati per definire il
rettangolo
L’oggetto Oval
Metodo
Oval(punto1,punto2)
getCenter()
getP1(), getP2()
Descrizione
Costruisce un ovale all’interno del rettangolo con vertici
opposti nei punti assegnati
Restituisce una copia del punto centrale dell’ovale
Restituisce una copia dei punti utilizzati per definire l’ovale
L’oggetto Polygon
Metodo
Polygon(punto1,punto2, ...)
getCenter()
getPoints()
Descrizione
Costruisce un poligono avente come vertici i punti
assegnati. I vertici possono anche essere definiti per mezzo
di una lista di punti
Restituisce una copia del punto centrale dell’ovale
Restituisce una lista di punti duplicati dei vertici
L’oggetto Text
Metodo
Text(punto, testo)
setText(testo)
getText()
getAnchor()
setFace(tipo)
setSize(dimensioni)
setStyle(style)
setTextColor(colore)
70
Descrizione
Costruisce un oggetto Text che visualizza il testo
specificato centrato sul punto centro. L’orientamento del
testo è orizzontale
Imposta il testo dell’oggetto
Restituisce il testo corrente
Restituisce un duplicato del punto centrale
Imposta il tipo di font. Valori possibili: 'helvetica',
'courier', 'times roman', 'arial'
Imposta le dimensioni del font. Valori possibili: da 5 a 36
Imposta lo stile del font. Valori possibili: 'normal',
'bold', 'italic', 'bold italic'
Imposta il colore del testo. (In alternativa setFill)
L’oggetto Entry
Gli oggetti di tipo Entry sono visualizzati come caselle di inserimento testo editabili dall’utente del
programma e supportano i metodi grafici generici move(), draw(finestra), undraw(),
setFill(colore), clone()
Metodo
Entry(punto, larghezza)
getAnchor()
getText()
setText(testo)
setFace(tipo)
setSize(dimensioni)
setStyle(style)
setTextColor(colore)
Descrizione
Costruisce un oggetto Entry con centro e larghezza
assegnati. La larghezza rappresenta il numero di caratteri
del testo che possono essere visualizzati
Restituisce un duplicato del punto centrale della casella
Restituisce il testo corrente nella casella
Imposta il testo della casella.
Imposta il tipo di font. Valori possibili: 'helvetica',
'courier', 'times roman', 'arial'
Imposta le dimensioni del font. Valori possibili: da 5 a 36
Imposta lo stile del font. Valori possibili: 'normal',
'bold', 'italic', 'bold italic'
Imposta il colore del testo.
L’oggetto Image
La libreria graphics fornisce, attraverso l’oggetto Image, le funzioni base per la visualizzazione ed
elaborazione elementare di immagini. La maggior parte delle piattaforme supporta almeno i formati gif e
ppm. L’oggetto Image implementa i metodi generici move(dx,dy), draw(finestra), undraw(),
and clone()
Metodo
Image(punto, nomeFile)
getAnchor()
getWidth()
getHeight()
getPixel(x,y)
setPixel(x,y,colore)
save(nomeFile)
Descrizione
Costruisce un’immagine centrata su punto, col contenuto
del file specificato. Se al posto del file si specificano
larghezza e altezza, viene creata un immagine trasparente
Restituisce un duplicato del punto centrale della casella
Restituisce la larghezza dell’immagine
Restituisce l’altezza dell’immagine
Restituisce una lista [red, green, blue]con i valori rgb
del pixel in posizione (x,y). Si noti che la posizione del pixel
è relativa all’immagine stessa e non alla finestra. L’angolo
superiore sinistro dell’immagine ha coordinate (0,0)
Imposta il pixel in posizione x,y col colore specificato (è
un’operazione lenta)
Salva l’immagine in un file. Il tipo di file è determinato
dall’estensione (ppm, gif)
71
I colori
I colori più frequenti sono indicati da stringhe: 'red', 'purple', 'green', 'cyan', ...
E’ possibile specificare gradazioni crescenti di scuro attraverso un numero (es. 'red1','red2','red3',...)
E’ anche possibile comporre i colori specificando numericamente (0..255) le percentuali di rosso, verde e
blu tramite la funzione color_rgb(red, green, blue).
L’aggiornamento della finestra grafica
Di solito la finestra grafica viene aggiornata ogni qual volta si richiama il metodo draw, oppure cambia lo
stato di visualizzazione di un oggetto.
Tuttavia, in alcune situazioni, può rendersi necessario forzare l’aggiornamento della finestra per rendere
visibili i cambiamenti. A tal fine si utilizza la funzione update()che causa il completamento di tutte le
operazioni di grafica pendenti.
All’opposto, per ragioni di efficienza, si può desiderare talvolta di disattivare l’aggiornamento automatico
della finestra ad ogni cambiamento degli oggetti grafici in essa contenuti. Per esempio, nelle animazioni, è
preferibile cambiare l’aspetto di più oggetti prima di passare alla visualizzazione del fotogramma
successivo.
Per controllare la modalità di aggiornamento, il costruttore della finestra grafica include un parametro
aggiuntivo chiamato autoflush. Per default, tale parametro è attivo. Se si desidera disattivarlo in modo
che l’aggiornamento non avvenga automaticamente, lo si deve impostare a False durante la costruzione
della finestra grafica
Win = GraphWin("animazione",400,400,autoflush=False)
In tal modo i cambiamenti agli oggetti grafici verranno mostrati durante gli intervalli di inattività del sistema
o tramite chiamata esplicita della funzione update().
72