- presentazione del sito
- Registrazione
- Eventi, mostre, convegni ed iniziative segnalate dalle aziende
- Recensioni ed articoli
- Le Mailing Lists
- La rivista Pc Ciechi
- Wiki
- Chi siamo
- Donazioni
- Un progetto degno di nota: Wintalbra
- Come navigare in questo sito
- rss
- Bancomat Accessibili sul territorio nazionale
- Contattaci
- I sostenitori di SpazioAusili
uno sguardo al python, parte prima.
inviato da donato taddei in privato, 05\02\2008, h. 17.14.
Questo testo è tratto dal sito italiano di python,
www.python.it
sezione documentazione/articoli
e fornisce una panoramica introduttiva sulle caratteristiche di questo linguaggio in generale in questa prima parte e per quanto riguarda i cosiddetti
moduli nella seconda, anche in cofronto a linguaggi funzionalmente o strutturalmente affini come java o perl.
Viene qui riportato perchè contiene quanto basta per cominciare ad esplorare, se non a decifrare e/o modificare e migliorare il codice di nvda, che come
si sa è scritto in tale linguaggio.
Donato Taddei
Uno sguardo al Python - parte prima
Esaminiamo il Python, un linguaggio di scripting object oriented, molto
chiaro nella sua sintassi, semplice ma potente che per le sue molteplici
virtù conquista ogni giorno maggiori consensi...
Ed ora, un po' di pubblicità
: Uno sguardo al Python
di Michele Sciabarrà
Java è un linguaggio che è venuto alla ribalta molto di recente, quando i
giochi sui linguaggi di programmazione sembravano fatti: chi avrebbe mai
immaginato, solo pochi anni fa, che si sarebbe potuto affermare in così
breve tempo un nuovo major programming language per il quale sono già
disponibili decine con ambienti di svilupp e numerose librerie? Allo
stesso modo, Python si è imposto quando sembrava non esserci spazio per
nuovi linguaggi di scripting: tra Perl, JavaScript, Tcl/Tk e Scheme non
sembrava esserci spazio per altri… In realtà nel mondo informatico ci sarà
sempre spazio per l'innovazione, fermo restando il fatto che i vecchi
sistemi non spariscono mai del tutto… vedi COBOL e FORTRAN.
Le similitudini tra Python e Java non finiscono qui: il bello di Java, a
parte l'aspetto "politico" di rappresentare una piattaforma alternativa a
Windows, è dato dal linguaggio stesso: Java sembra riassumere per certi
versi il meglio del C++ e del Visual Basic. Java è moderno, object
oriented senza compromessi ed esagerazioni; è più potente del Visual
Basic, da cui eredita la capacità di creare intefacce grafiche con
semplicità; si presenta ben più semplice del C++, da cui deriva molte
potenzialità, espresse però in maniera più semplificata e chiara sia
sintatticamente che semanticamente.
La storia del Python sembra molto simile nell'ambito dei linguaggi di
scripting in ambiente Unix. Perl e Tcl/Tk sono stati per anni l'unica
opzione; entrambi sono derivati dallo scripting di shell, ed entrambi con
pregi e difetti (sintassi e semantica astrusa il Perl, alcune limitazioni
di scalabità il Tcl/Tk). Python sembra riassumere per certi versi il
meglio del Perl e del Tcl/Tk. Python è moderno, object oriented senza
compromessi ed esagerazioni; è più potente del Tcl/Tk, da cui eredita la
capacità di creare intefacce grafiche con semplicità; si presenta ben più
semplice del Perl, da cui deriva molte potenzialità espresse però in
maniera più semplificata e chiara sia sintatticamente e semanticamente.
Non è un caso che l'ultima frase sia analoga dalla precedente sostituendo
Perl a C++, Tcl/Tk a Visual Basic e Python a Java…
In effetti la mia esperienza personale con il Python assomiglia molto alla
mia esperienza con il Java. Non ho mai voluto usare il Visual Basic,
preferendovi per anni il C++, e scontrandomi regolarmente con le sue
astrusità, finché ho scoperto Java: la versione più semplice del C++ che
offre molto dei vantaggi del Visual Basic… e da allora ho usato quasi
esclusivamente Java. Analogamente non ho mai voluto usare il Tcl/Tk,
preferendovi per anni il Perl, e scontrandomi regolarmente con le sue
astrusità finchè non ho scoperto il Python…
Primo impatto
Python è un interprete. Niente di strano trattandosi di un linguaggio di
scripting. A differenza di altri però può essere utilizzato
interattivamente. Eseguendo python dalla riga di comando (che sia Unix o
NT) otteniamo il prompt (in questo caso su NT):
PythonWin 1.5.1 (#0, Apr 13 1998, 20:22:04) [MSC 32 bit (Intel)] on win32
Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
>>>
Dopo il >>> possiamo digitare dei comandi e quindi eseguire delle semplici
operazioni:
>>> 2+2
4
>>> a=5
>>> a+1
6
>>> def sum(a,b): return a+b
>>> sum(4,5)
9
Come si vede, il Python è innanzitutto un valutatore di espressioni, ma
consente di assegnare variabili e definire delle funzioni. Fin qui niente
di eccezionale. Ora però cominciamo a fare qualcosa un po' più audace.
>>> __builtins__
>>> dir(__builtins__)
['ArithmeticError', … OMISSIS …
'abs', 'apply', 'callable', 'chr', 'cmp', 'coerce', 'compile', 'complex',
'delattr', 'dir', 'divmod', 'eval', 'execfile', 'filter', 'float',
'getattr', 'globals', 'hasattr', 'hash', 'hex', 'id', 'input', 'int',
'intern', 'isinstance', 'issubclass', 'len', 'list', 'locals', 'long',
'map', 'max', 'min', 'oct', 'open', 'ord', 'pow', 'range', 'raw_input',
'reduce', 'reload', 'repr', 'round', 'setattr', 'slice', 'str', 'tuple',
'type', 'vars', 'xrange']
La variabile __builtins__ è di tipo modulo, come dice il messaggio
ottenuto dalla sua valutazione; si tratta del modulo che contiene tutti i
builtins, ovvero le funzioni predefinite del sistema. Per vedere il
contenuto di un modulo (o di un qualsiasi namespace in generale - un
modulo è un particolare namespace) posso usare il builtin dir, che in
questo caso mi consente di elencare tutti gli altri builtin. I builtin
sono funzioni immediatamente disponibili senza particolari operazioni.
Continuiamo le nostre esplorazioni, provando ad utilizzare un builtin.
>>> open
>>> open("c:\\autoexec.bat")
>>> x=open("c:\\autoexec.bat")
>>> dir(x)
['close', 'closed', 'fileno', 'flush', 'isatty', 'mode', 'name', 'read',
'readinto', 'readline', 'readlines', 'seek', 'softspace', 'tell',
'truncate', 'write', 'writelines']
>>> x.readline
>>> x.readline()
'rem - By Windows 95 Network - C:\\WINDOWS\\net start\012'
Vediamo se vi è chiaro quello che ho fatto: open è un builtin; infatti
valutando open mi viene comunicato che si tratta di una funzione builtin
(un oggetto quindi di tipo diverso dal modulo visto prima); questo oggetto
può essere usato invocandolo con un parametro, ovvero il nome di un file:
così facendo ottengo un altro oggetto che rappresenta un file aperto. Per
utilizzare il file lo salvo in una variabile e provo ad esaminarne il
contenuto con dir, scoprendo che l'oggetto contiene al suo interno una
serie di funzioni (o più correttamente metodi). Provo ad utilizzare la
readline, che è una funzione e non una proprietà e quindi invoco la
funzione, senza parametri, ottenendo quello che mi aspetto: la prima riga
del file AUTOEXEC.BAT che ho aperto.
I builtin sono immediatamente disponibili, ma si tratta di un caso
particolare: in generale le funzioni è necessario importarle. Come è
possibile accedere ai metodi di un oggetto, è anche possibile accedere
alle funzioni presenti in un file, o meglio modulo. Per usare le funzioni
di un modulo, occorre importarlo. Vediamo subito come si fa, esaminando il
modulo per le espessioni regolari (un assoluto must per chi vuole
utilizzare il Python come un sostituto per il Perl).
>>> re
Traceback (innermost last):
File "", line 0, in ?
NameError: re
>>> import re
>>> re
>>> match
Traceback (innermost last):
File "", line 0, in ?
NameError: match
>>> from re import match
>>> match
Non ci interessa in questa sede il funzionamento del modulo re, per il
momento ci limitiamo ad esaminanare il meccanismo di importazione.
Inizialmente re non è disponibile, lo diventa dopo che eseguiamo import
re. A questo punto possiamo vedere il modulo, ma le funzioni in esso
contenute (che in questo caso non sono metodi) sono accessivibili solo con
la sintassi puntata: re.match. È però possibile rendere accessibile
definitivamente una funzione senza dove specificare il modulo con la
sintassi from re import match. Notare che in questo modo viene resa
disponibile per l'accesso immediato soltanto una funzione, anche se
possono essere importate tutte (ma in generale, a meno di moduli semplici,
non è il caso).
Sequenze e dizionari
In Python abbiamo tre categorie di tipi di dato. I tipi primitivi (interi
e float), gli oggetti e le sequenze. Le sequenze presenti in Python
attualmente sono stringhe, liste e tuple. Vediamo innanzitutto le stringhe
>>> s = 'Hello'
>>> s = s+', world'
>>> s
'Hello, world'
>>> len(s)
12
>>> s[0:5]
'Hello'
>>> s[7:]
'world'
>>> s[0]
'H'
>>> s[-1]
'd'
>>> dir(s)
[]
>>> x='a'
>>> x=x+'b'
>>> x
'ab'
Le stringhe possono essere espresse con una costante: basta scrivere i
caratteri che la compongono tra virgolette, singole o doppie. Le variabili
in Python, come ormai dovrebbe essere chiaro, non sono tipizzate e non
vanno dichiarate: quindi per creare una variabile contentente una stringa
basta assegnare una costante stringa alla variabile. Le stringhe sono
immutabili: questo vuol dire che una volta create non possono essere
modificate, si può solo creare un'altra stringa. Le stringhe possono
essere concatenate utilizzando l'operatore +, come si vede nell'esempio,
ma in questo caso vengono buttate via le due stringhe preesistenti,
costruendone una nuova risultante dalla concatenazione delle due
precedenti. Le stringhe, come tutte le sequenze in genere, sono
indicizzabili tramite l'operatore [], che può specificare un range,
separato dai due punti: questa operazione viene chiamata slicing.
Riferiamoci all'esempio di prima. Possiamo notare subito che i range
partono da 0 e che il range s[a:b] indica tutti gli elementi da a incluso
a b escluso. Usare un numero negativo come indice equivale ad indicizzare
a partire dall'ultimo elemento; quando ometto il primo elemento del range
si intende 0, quando ometto il secondo si intende il len della sequenza.
Un esame della stringhe con dir rivela che non ha metodi: questo significa
che una stringa può essere manipolata soltanto utilizzando i builtin e gli
operatori predefiniti. Un'altra sequenza immutabile è la tupla:
>>> x = 1,2,3
>>> x
(1, 2, 3)
>>> a,b,c = x
>>> a
1
>>> b
2
>>> c
3
>>> x[0:1]
(1,2)
>>> x,y = 7,8
>>> x+y
15
Separando con una virgola una serie di elementi si costruisce una tupla, o
meglio si impaccano (packing) gli elementi un una tupla. Questa operazione
ha il suo constrario nello spacchettamento (unpacking) della tupla, che si
ottiene ponendo una serie di variabili a sinistra di un assegnamento.
Essendo le tuple sequenze, anche su di esse si può operare con lo slicing,
come le stringhe. Python ha dunque l'assegnamento multiplo, che
tecnicamente è un packing ed unpacking di tupla. Le tuple sono comode in
molti casi, ma sono immutabili come le stringe, e si può operare con esse
solo utilizzando poche operazioni, quelle standard per le sequenze,
riassunte in Tabella 1. Esiste una struttura dati molto più flessibile, ma
ovviamente anche più inefficiente, ovvero la lista:
>>> x=[1,3]
>>> x
[1, 3]
>>> x.append(4)
>>> x
[1, 3, 4]
>>> x.insert(1,2)
>>> x
[1, 2, 3, 4]
>>> x.reverse()
>>> x
[4, 3, 2, 1]
>>> dir(x)
['append', 'count', 'index', 'insert', 'remove', 'reverse', 'sort']
Tabella 1OperazioneRisultato
X in SCerca X nella sequenza S
X not in SInverso del precedente
S + TConcatezione generica di sequeze
S * NIterazione di S per N volte
S[I]I-simo elemento di S
S[I:J]Slice da I incluso a J escluso.
len(S)Lungheszza della sequenza
Min(S), Max(S)Minino e massimo di S
A differenza delle tuple, le liste sono mutabili e si possono eseguire più
operazioni su di esse. Le liste possono essere create utilizzando
l'apposita sintassi, comprendo gli elementi tra parentesi quadre, e su di
esse si può operare utilizzando una serie di metodi predefiniti: append,
insert, reverse, eccetera, come si può vedere nell'esempio, oltre al
solito slicing. Vediamo infine i dizionari, ovvero gli array associativi
che sono anche essi tipi primitivi in Python:
>>> x={'a':1, 'b':2}
>>> x
{'b': 2, 'a': 1}
>>> x['a']
1
>>> x['c']=3
>>> dir(x)
['clear', 'copy', 'get', 'has_key', 'items', 'keys', 'update', 'values']
>>> x.keys()
['b', 'c', 'a']
>>> x.values()
[2, 3, 1]
>>> x.items()
[('b', 2), ('c', 3), ('a', 1)]
Il funzionamento dovrebbe essere abbastaza ovvio. Le costanti per definire
i dizionari sono della forma { key:val, keys:val, … } . Per accedere agli
elementi si usa la sintassi per l'indicizzazione di una sequenza; si può
assegnare un elemento per crearlo, e si può eliminare un elemento con del.
I dizionari non sono sequenze, ma li tratto in questo paragrafo per
affinità con le altre strutture dati primitive. Se serve si possono
ottenere facilmente le sequenze delle chiavi, dei valori e di tutti gli
elementi (una lista di tuple).
Controllo di flusso
Python è un linguaggio imperativo e ha quindi il controllo di flusso
usuale, con if, while e for. Un aspetto importante e caratteristico del
Python è la modalità di "accorpamento" dei comandi, ovvero come si
definiscono i blocchi. I linguaggi tradizionali usano le parentesi: le
graffe C e Java, begin-end il Pascal ecceter. Il Python usa l'indentazione
per raggruppare gli statementi. Vediamo subito un esempio:
>>> def max(a,b):
... if a>b:
... return a
... else:
... return b
...
>>> max(1,2)
2
Tabella 2if :
[elif : ]*
[else: Comune If/then/else in Python
while :
[else: ]Comune While in Python - il blocco in else è eseguito
dop la condizione se il ciclo non termina con un break
for in :
[else: ]Itera per ogni elemento della sequenza e lo assegna
alla variabile target - il blocco in else è eseguito dopo la
condizione se il ciclo non termina con un break
breakTermina un ciclo for o while
continueEsegue la successiva iterazione di un ciclo for o while
return []Ritorna il risultato dalla funzione o metodo
corrente - se result è omesso ritorna None
I comando if, while, for, def sono composti, quindi devono essere seguite
da un blocco, che viene separato dalla condizione con due punti. Il blocco
comincia dalla riga successiva e finisce in una indentata quanto la
corrente o meno. Visivamente si ha quello che ci si aspetta: tutte le
linee seguenti ad un comando composto e più indentate di esso appartengono
al blocco di quel comando. Oltre alla sintassi già di per sé abbastanza
chiara, questa caratteristica è una marcia in più che contribuisce a
rendere i sorgenti in Python estremamente leggibili: quella che prima era
solo una norma estetica in Python diventa una regola di programmazione.
Come dire che un programma è corretto solo se è anche scritto ordinato!
Inoltre, l'uso dell'indentazione elimina molti problemi abbastanza
frequenti legati al matching delle parentesi. Infine questo contribuisce a
rendere la sintassi minimale, quello che si vuole da un linguaggio di
scripting comodo e veloce da usare. Gli elementi del controllo di flusso
sono riassunti in tabella 2. Esaminiamoli uno ad uno.
L'if è il consueto blocco condizionale. L'unica particolarità da notare è
che, poichè gli if in cascata risulterebbero sconvenienti da scrivere, per
esempio:
>>> if a=1:
... …
... else:
... if a=2:
... …
... else:
... if a=3:
... …
... else:
esiste la clausola elif, per cui l'esempio di sopra può essere scritto più
semplicemente e chiaramente in Python come:
>>> if a=1:
... …
... elif a=2:
... …
... elif a=3
... …
... else:
... …
Il ciclo while è simile all'if eccetto che itera il corpo finchè la
condizione non è verificata. La particolarità da notare in questo caso è
una comoda clausola else che viene eseguita solo quando la condizione
diventa falsa. Sono disponibili i comandi break per interrompere il ciclo
e continue per continuare il ciclo alla iterazione successiva. Notare che
l'else del while (e anche del for che vedremo dopo) non viene eseguito se
il ciclo termina con un break. Questo rende agevole scrivere certi cicli
in cui si deve distinguere se il ciclo è stato terminato normalmente
oppure no. Per esempio, supponiamo di voler cercare una riga in un file
per fare dei calcoli, e ritornare il valore speciale None se la riga non è
stata trovate nel file. Ecco come si può fare in Python:
>>> while
... if :
... break
... else:
... return None
...
... return
Infine il for, che è speciale, nel senso che non è un while compattato
come in Java o C. Il for itera su tutti gli elementi di una sequenza:
>>> for i in 'abc':
... print i, "-",
...
a - b - c -
>>> for i in 1,2,3:
... print i*i
...
1
4
9
Per inciso notiamo la print, che prende i suoi argomenti separati da
virgole; se l'ultimo argomento è omesso (notare la virgola senza niente
dopo) la print non genera un newline, come fa nel secondo caso. Il for può
essere usato sulle stringhe, sulle tuple e anche sulle liste. In Python
quindi non c'è un modo esplicito per andare da 6 a 12 a passi di 2, ma
occorre appoggiarsi alla funzione range(, [,]) che
costruisce una lista con gli elementi necessari. Quindi questo è il modo
corretto per andare da 6 a 12 a passi di due:
>>> for i in range(6,13,2):
... print i,
...
6 8 10 12
Notare che abbiamo usato 13 perchè in un range il limite superiore (12) è
escluso.
Python supporta la programmazione ad oggetti in maniera consistente ed
elegante, ed ha una libreria di classi piuttosto ampia che copre molte
necessità. La dichiarazione delle classi in Python è piuttosto complessa,
per cui per motivi di spazio non approfondiremo qui l'argomento ma lo
rimandiamo ad un articolo successivo.
Windows e Java
Python è nato originariamente in ambiente Unix, come supporto per un
progetto in cui i linguaggi esistenti non erano adeguati, e si è diffuso
quando l'autore (Guido Van Rossum) ha reso disponibile il linguaggio in
sorgente su UseNet (le News di Internet). Però il Python non è legato ad
Unix in maniera così forte come il Perl, e infatti il linguaggio si trova
a suo agio senza scomporsi anche in altri ambienti. In particolare sono
disponibili due interessanti implementazioni: il PythonWin per Windows e
il JPython per Java. Il PythonWin è innanzitutto il porting del Python in
ambiente Windows, corredato di una sorta di IDE e di librerie specifiche
per Windows. Si può vedere in Figura 1 uno snapshot ottenuto con il
PyhonWin che dimostra come esso consenta di accedere ad una buona parte
della API di Win32. PythonWin ha numerose altre armi al suo arco, tra cui
l'accesso all'OLE Scripting: di conseguenza si può usare Python per le ASP
ma anche per scriptare Word o Excel.
Figura 1
Il Python può anche essere utilizzato per scriptare la Java Platform:
esiste infatti una reimplementazione in Java, chiamata JPython. In questo
contesto l'interprete Python tradizionale, che è scritto in C, viene
chiamato CPython, e il JPython è la versione dell'interprete in Java. La
cosa interessante è la compatibilità tra le versioni: infatti il JPython e
il CPython usano le stesse librerie! Una cosa interessante è che il
JPython consente di avere accesso con assoluta semplicità alle librerie
Java e può essere quindi utilizzato per sperimentare interattivamente con
Java. Per esempio ecco un listatino che crea una finesta con un bottone
digitato direttamenete al prompt del JPython:
>>> import java
>>> from java import awt
>>> f = awt.Frame("Demo")
>>> b = awt.Button("Ok")
>>> l = awt.Label("Hello")
>>> f.add("Center", l)
>>> f.add("South", b)
>>> f.setSize(100,100)
>>> f.setVisible(true)
>>> f.setVisible(1)
Conclusioni
Non concluderò l'articolo dicendo che vale la pena di provarlo perchè
arricchisce la vostra cultura. Io il Python lo uso, per progetti reali e
in contesti commerciali. Mi limiterò a raccontare come ho cominciato ad
usarlo. Devo dire che quando ho dato una buona occhiata al Python ero
molto scettico ma anche abbastanza frustrato: avevo perso alcune ore per
risolvere un baco in uno script Perl in teoria da cinque minuti, dovuto al
fatto che non avevo afferrato bene un dettaglio sintattico. Più ci pensavo
più mi sembrava assurdo che dopo quattro anni che lavoravo con il Perl,
ancora non ne avevo digerito completamente la sintassi. Quella sintassi
così stramba per me è un impiccio che costringe ad avere sempre il manuale
sottomano (non mandatemi email dicendomi che non siete d'accordo, vi
prego!). Perché nessuno aveva ancora inventato un linguaggio di scripting
chiaro e pulito come Java?
Mi serviva un linguaggio di scripting (Java non è un linguaggio di
scripting) innanzitutto portabile tra Unix e NT, che avesse la stessa
plasticità del Perl, con strutture dati primitive potenti come tabelle
hash e liste. Il linguaggio che cercavo doveva gestire bene le stringhe,
con espressioni regolari comprese nel linguaggio, e doveva essere
interpretabile senza alcuna ricompilazione in modo da poter scrivere uno
script ed eseguirlo anche con solo l'editor (o meglio ancora con il cat
>file o il copy con: file). Come il Perl il linguaggio doveva essere poco
tipizzato per non perdere tempo a fare dichiarazioni e progettazione per
semplici script (per esempio in Java solo per impostare un pattern tipo
*.txt o un event-handler occorre dichiarare una classe!). Questo
fantomatico linguaggio doveva avere una sintassi più pulita e un
orientatamento agli oggetti decisamente più netto e meno arzigogolato del
Perl. E se fosse dotato anche di una shell con la quale interagire
(mancanza del Perl - per farlo si deve lanciare il debugger!) non sarebbe
stato male. Infine, possibilmente si doveva trattare di linguaggio che
avesse qualche supporto, ovvero non il solito linguaggetto geniale tirato
fuori da qualche ricercatore che non usa nessuno. Avevo sentito parlare
del Python e del fatto che era abbastanza usato, ma mi ci volevano un paio
di giorni per studiarlo. Quando finalmente ho trovato il tempo e ho avuto
modo di approfondire meglio il linguaggio, ho capito di aver trovato
quello che cercavo. E a giudicare dal supporto che circola su Internet, a
quanto pare non sono il solo.
Bibliografia
[1]
http://www.python.org
- " Python Software Activity", il sito
principale del Python dove si può trovare di tutto relativo al Python
[2] Guido Van Rossum "Programming Python", O'Reilly 1997, il libro
ufficiale sul Python scritto dall'autore del linguaggio.
Michele Sciabarrà, laureato in Scienze dell'Informazione, è direttore
tecnico di SATORI Network Solutions, ditta marchigiana focalizzata su Java
e le tecnologie di Internet. Programma in svariati linguaggi da 15 anni, e
in Java da quando il linguaggio era in versione alpha. È stato tra gli
espositori di applicazioni Java già alla 1st Italian Java Conference, ha
scritto decine di articoli su Java e sviluppato numerose applicazioni in
Java. Mantiene sul Web un corso online di Java in italiano
(http://www.satorins.com/CorsoJava)
--------------------------------------------------------------------------------
Internal Virus Database is out-of-date.
Checked by AVG Free Edition.
Version: 7.5.516 / Virus Database: 269.6.1/776 - Release Date: 25/04/2007 12.19