<!doctype linuxdoc system>

<!-- LyX 1.1 created this file. For more info see http://www.lyx.org/ -->
<article>
<title>
Python: facile, pulito, potente
</title>
<author>
Magnus Lie Hetland e Alex Martelli
</author>
<sect>
Cos'è Python? 
<p>
Python é un linguaggio interpretato, interattivo, orientato agli oggetti;
 può essere, per vari aspetti, paragonato a linguaggi come Tcl, Perl, e Java.
 
</p>
<p>
Python combina una potenza notevole con una sintassi particolarmente limpida;
 la sua implementazione, estremamente portatile, é disponibile per tanti tipi
 di Unix, Linux, Windows, DOS, OS/2, Mac, Amiga... nella versione Jython, in
 particolare, Python può appoggiarsi a una macchina virtuale Java, e quindi
 girare dovunque Java sia disponibile (ad esempio, come applet all'interno di
 un browser). 
</p>
<p>
É un linguaggio solido e stabile: il suo sviluppo, iniziato dall'autore
 Guido van Rossum nel 1990 presso il CWI di Amsterdam, continuó poi al CNRI
 di Reston, Virginia, successivamente presso i PythonLabs della BeOpen Inc.,
 e oggi presso l'azienda Digital Creations. Tutte le varie implementazioni e
 le librerie di Python sono Open Source.
</p>
<p>
Vari siti Web come <url url="http://www.python.org" name="">, <url url="http://www.pythonware.com/daily/" name="">, <url url="http://www.vex.net/~x/parnassus/" name=""> (e, in italiano, il sito <url url="http://web.tiscalinet.it/python" name="">) contengono molto materiale
 utile sul linguaggio, e una dovizia di puntatori ad altri materiali.
</p>
<sect>
Interpretato o compilato? 
<p>
Python, come Java o Perl, é in realtà entrambe le cose -- sia compilato,
 sia interpretato.
</p>
<p>
Il compilatore Python trasforma il testo (codice sorgente) dei nostri programmi
 in un codice intermedio, detto byte-code, che può essere visto come &quot;codice-macchina&quot;
 per una macchina &quot;virtuale&quot; studiata apposta per eseguire programmi
 Python; l'interprete Python vero e proprio é una implementazione in software
 di questa macchina virtuale. Come in Perl, e a differenza che in Java, si può
 richiedere direttamente l'esecuzione dei file-sorgente (normalmente con estensione
 .py), senza necessità di un esplicito passaggio di compilazione; come in Java,
 e a differenza che in Perl, il byte-code non viene solo preparato &quot;al
 volo&quot; in memoria, ma viene anche salvato su disco (con estensione .pyc),
 cosí che in esecuzioni successive non occorrerà compilarlo nuovamente (la compilazione
 é però automaticamente ri-eseguita se il file sorgente é piú aggiornato di
 quello contenente il byte-code).
</p>
<p>
Esistono compilatori Python che producono codice per altre macchine virtuali:
 Jython produce bytecode per una JVM (file .class), Python.NET produce il codice-intermedio
 MSIL tipico della nuova piattaforma .NET (file .msil). La "versione-base" di
 Python, essendo scritta in C (sia il compilatore, sia la macchina virtuale),
 è anche denominata C-Python ove occorra distinguerla da Jython e Python.NET;
 è sul classico C-Python che ci concentreremo in questo articolo (non che le
 altre versioni ne differiscano molto!).
</p>
<sect>
Per cosa si usa Python? 
<p>
Come altri linguaggi di scripting, come Tcl e Perl, Python é particolarmente
 adatto per compiti come le operazioni di Web (server-side, sotto forma di script
 CGI, ovvero con architetture piú moderne, come FastCGI, mod_python, etc; client-side,
 &quot;entro il browser&quot;, opzione per cui Python offre varie possibilità
 -- JPython permette di usare Python per scrivere applet al posto di Java, Active
 Scripting permette di usare Python al posto, ad esempio, di Javascript -- esiste
 anche un browser, detto Grail, scritto interamente in Python).
</p>
<p>
Lo scripting (Python in particolare) é poi ideale per vari compiti di gestione
 di sistema (al posto dei deboli, scomodi shell-script), come colla fra componenti
 scritti in altri linguaggi (ad esempio, Python é ampiamente usato a questo
 scopo nell'ambito del calcolo scientifico), e, facilmente incorporato in applicazioni
 (magari ricche e complesse), per la personalizzazione e automatizzazione delle
 applicazioni stesse.
</p>
<p>
Ma, per Python, questo é solo l'inizio.
</p>
<p>
La sua unica combinazione di potenza, semplicità, e pulizia, lo rendono
 ideale per compiti di prototipazione (sviluppo esplorativo di componenti che,
 se occorre, possono poi eventualmente essere reimplementati ad esempio in C)
 e anche per la scrittura di interi, complessi sistemi (Zope, <url url="http://www.zope.org" name="">, é ad esempio
 interamente in Python, e lo stesso può dirsi per molta dell'infrastruttura
 di popolari servizi disponibili in rete, come eGroups, Google, Infoseek, Yahoo,
 ...).
</p>
<p>
Sempre a titolo di esempio, segnaliamo anche un semplice DBMS relazionale
 SQL (transazionale, con la possibilità di uso client/server in TCP/IP), <em>Gadfly</em>,
 interamente scritto in Python -- vedi <url url="http://www.chordate.com/kwParsing/gadfly.html" name=""> (le sue prestazioni su database grossi
 possono essere <em>sostanzialmente</em> migliorate usando, per i bassissimi livelli,
 il modulo scritto in C 'kjBuckets'; e anche questo è tipico: una volta che
 l'intera architettura di un sistema, sviluppata in Python, permette di individuare
 i <em>colli di bottiglia</em> computazionali, un'ultima ottimizzazione può compiersi
 codificando in C o C++ i <em>bassissimi livelli</em> di questi colli di bottiglia).
 Anche Gadfly è liberamente e gratuitamente scaricabile ed utilizzabile, secondo
 il modello Open Source.
</p>
<sect>
Da dove comincio?
<p>
Scarica e installa l'ultima versione di Python dal sito <url url="http://www.python.org/" name=""> <footnote>
Gli esempi che seguono si riferiscono a Python versione 2.0 o superiore. </footnote>
 (puoi trovare il tarball dei sorgenti o il pacchetto RPM direttamente
 da installare, oltre alle versioni di altri sistemi operativi e la documentazione
 da leggere on-line o da stampare). Accertati che la directory d'installazione
 sia nel <tt>PATH</tt> (automatico se installi da RPM). Hai ora a disposizione un ambiente
 integrato di sviluppo (si chiama <tt>idle</tt>, e comprende editor specializzato, interprete
 interattivo, debugger, class browser, documentazione...) e un piú semplice
 programma chiamato <tt>python</tt>, meno ricco e potente ma piú facile da imparare ad
 usare -- ci concentriamo su quest'ultimo, ma conviene sicuramente anche esplorare
 <tt>idle</tt>, che alla lunga può offrire notevoli comodità. Eseguendo <tt>python</tt> senza
 argomenti da qualsiasi shell, otterrai una risposta del tipo:
</p>
<p>
<verb>
Python 2.0b2 (&num;6, Sep 26 2000, 14:59:21) &lsqb;gcc 2.9.37 (Intel)&rsqb; on linux 
Type &quot;copyright&quot;, &quot;credits&quot; or &quot;license&quot; for more information. 
&gt;&gt;&gt; 
</verb>
</p><p>
e puoi immettere interattivamente codice Python al prompt '<tt>&gt;&gt;&gt;</tt>'
 -- verrà eseguito immediatamente, il che é comodo per provare. Ad esempio,
 immettendo la riga di codice: 
</p>
<p>
<verb>
print &quot;Hello, world!&quot;
</verb>
</p><p>
il messaggio verrà visualizzato. Alla fine, premerai <tt>Ctrl-D</tt> per terminare
 la sessione interattiva di Python. Per programmare &quot;davvero&quot;, scriverai
 il codice Python, con qualsiasi editor di testi (ad esempio, <tt>vim</tt>), in un file
 di testo (chiamato, ad esempio, <tt>hello.py</tt>), e lo eseguirai (da una shell) col
 comando: 
</p>
<p>
<verb>
python hello.py
</verb>
</p><p>
se <tt>hello.py</tt> contiene la stessa, unica riga <tt>print &quot;Hello, world!&quot;</tt>,
 anche questo mostrerà lo stesso messaggio. Esistono inoltre altri modi di rendere
 direttamente eseguibile un file di testo contenente un programma (<em>script</em>) Python:
 su Linux, basta renderlo eseguibile con il comando <tt>chmod +x</tt> e assicurarsi che
 inizi con una prima riga del tipo:
</p>
<p>
<verb>
&num;!/usr/bin/env python 
</verb>
</p><p>
Il programma <tt>hello.py</tt> potrà ora venire eseguito direttamente digitandone
 il nome (ed eventualmente il directory, come per qualsiasi altro programma)
 da qualsiasi shell.
</p>
<sect>
Com'é fatto Python?
<p>
Python é praticamente <em>pseudo-codice eseguibile</em>. Una variabile non ha tipo
 e non viene dichiarata: appare quando le si assegna qualcosa, sparisce quando
 non la si usa piú. L'assegnazione si ottiene con l'operatore <tt>=</tt> ; l'eguaglianza
 si controlla con l'operatore <tt>==</tt>. Si possono assegnare molteplici variabili
 simultaneamente: 
</p>
<p>
<itemize>
 <item>
<tt>x,y,z = 1,2,3</tt> 
 <item>
<tt>prima, seconda = seconda, prima</tt> 
 <item>
<tt>a = b = 123</tt>
</itemize>
</p><p>
I blocchi sono indicati dall'indentazione, e solo dall'indentazione (niente
 <tt>BEGIN/END</tt>, niente parentesi graffe). Una struttura di controllo fondamentale
 é <tt>if</tt> (questi due esempi sono equivalenti) : 
</p>
<p>
<verb>
if x &lt; 5 or (x &gt; 10 and x &lt; 20): 
    print &quot;Il valore é OK.&quot;   &num; qui siamo dentro il blocco if
&num; qui siamo fuori dal blocco if

if x &lt; 5 or 10 &lt; x &lt; 20: 
    print &quot; Il valore é OK.&quot;
</verb>
</p><p>
Ci sono poi i cicli: 
</p>
<p>
<verb>
for i in &lsqb;1,2,3,4,5&rsqb;: 
    print &quot;Iterazione numero&quot;, i

x = 10 
while x &gt;= 0: 
    print &quot;x non é ancora negativo&quot;
    x = x-1
</verb>
</p><p>
La variabile-indice del ciclo <tt>for</tt> itera sugli elementi di una lista (una
 costante lista può essere scritta con parentesi quadre e virgole, come nell'esempio).
 Per fare un &quot;normale&quot; ciclo di <tt>for</tt> (cioè uno in cui la variabile
 indice itera su di una sequenza di numeri), si può usare la funzione intrinseca
 <tt>range()</tt>: 
</p>
<p>
<verb>
&num; Stampa i numeri da 0 a 99 inclusi 
for value in range(100): 
    print value 
</verb>
</p><p>
(La riga che inizia con <tt>&num;</tt> é un commento, e viene quindi ignorata da
 Python). Attenzione: Python (come Java, C, C++,...) é case-sensitive -- <tt>x</tt> e
 <tt>X</tt> sono due variabili differenti... non é un problema, ma attenzione che questo
 non provochi errori!
</p>
<sect>
I/O in Python
<p>
Quanto visto finora basta (in teoria) per implementare qualsiasi algoritmo
 in Python ed emettere i risultati su standard output. Aggiungiamo alcuni fondamenti
 di input/output. Per avere input dall'utente tramite un prompt di testo, si
 usa la funzione intrinseca <tt>input</tt>: 
</p>
<p>
<verb>
x = input(&quot;Immetti un numero: &quot;) 
print &quot;Il quadrato di&quot;, x, &quot;é&quot;, x*x
</verb>
</p><p>
La funzione <tt>input</tt> mostra il prompt passatole (che può essere vuoto) e aspetta
 che l'utente immetta una qualsiasi espressione Python. In questo caso ci serve
 un numero -- se viene immesso qualcosa d'altro, tipo una stringa, il programma
 va in errore (queste eccezioni possono essere gestite, ma qui non ce ne occuperemo).
</p>
<p>
Se si desidera che l'input dell'utente sia mantenuto alla lettera come
 stringa (stringa, allora, del tutto arbitraria), si userà invece la funzione
 intrinseca <tt>raw_input</tt> (per convertire una stringa <tt>s</tt> ad intero, si potrà poi
 usare <tt>int(s)</tt>). <footnote>
Per immettere una stringa in risposta ad input, l'utente dovrá usare le
 virgolette (le stringhe Python possono essere racchiuse fra virgolette semplici
 o doppie, non fa alcuna differenza). </footnote>
 Spesso si vogliono leggere e scrivere file di testo; anche questo é facile
 -- ad esempio, per copiare &quot;<tt>fin.txt</tt>&quot; su &quot;<tt>fou.txt</tt>&quot; si può
 scrivere (leggendo subito tutte le righe, poi eseguendo un ciclo su tutto l'insieme
 delle righe lette): 
</p>
<p>
<verb>
fou=open(&quot;fou.txt&quot;,&quot;w&quot;)
for line in open(&quot;fin.txt&quot;).readlines():
    fou.write(line)
</verb>
</p><p>
In alternativa, e in modo del tutto equivalente, si puó leggere una sola
 riga alla volta: 
</p>
<p>
<verb>
fou=open(&quot;fou.txt&quot;,&quot;w&quot;)
fin=open(&quot;fin.txt&quot;,&quot;r&quot;)
while 1:
    line = fin.readline()
    if not line:
        break
    fou.write(line)
</verb>
</p><p>
(<tt>break</tt> interrompe il ciclo corrente). 
</p>
<p>
Il secondo argomento della funzione intrinseca <tt>open</tt> dice se stiamo aprendo
 il file in lettura o in scrittura; é facoltativo, e il default é la lettura.
 <tt>readlines</tt> restituisce tutte le righe, in sequenza, pronte ad esempio per un'interazione
 con <tt>for</tt>; <tt>readline</tt> (al singolare, cioè senza la <tt>s</tt> finale) restituisce solo <em>la
 prossima riga</em> ogni volta che viene chiamata (ovvero, un valore falso, se non
 vi sono piú righe da restituire). Un'altra possibilità molto comoda per la
 lettura di file di testo é offerta dal modulo <tt>fileinput</tt>, che illustreremo fra
 breve.
</p>
<p>
A volte, si vogliono formattare dei dati ottenendo una stringa (ad esempio
 per emetterla); questo si può fare con l'operatore <tt>&percnt;</tt>, che prende sulla
 sinistra una stringa di formato (molto simile alla stringa di formato di una
 <tt>printf</tt> del C) e sulla destra una sequenza di valori, e restituisce una stringa.
 Ad esempio, per numerare le righe emesse, il ciclo potrebbe essere modificato
 nel modo seguente : 
</p>
<p>
<verb>
fou=open(&quot;fou.txt&quot;,&quot;w&quot;)
fin=open(&quot;fin.txt&quot;,&quot;r&quot;)
i=0
while 1:
    line = fin.readline()
    if not line:
        break
    i=i+1
    fou.write(&quot;&percnt;d: &percnt;s&quot; &percnt; i, line)
</verb>
</p><sect>
Liste
<p>
Sinora, abbiamo illustrato le strutture di controllo e l'input/output --
 ora, ci servono delle belle strutture dati. Le piú importanti sono liste e
 dizionari. Le liste si scrivono con parentesi quadre e virgole, e (naturalmente)
 possono anche essere annidate:
</p>
<p>
<verb>
name = &lsqb;&quot;Cleese&quot;, &quot;John&quot;&rsqb;
x = &lsqb; &lsqb;1,2,3&rsqb;, &lsqb;y,z&rsqb;, &lsqb; &lsqb; &lsqb; &rsqb; &rsqb; &rsqb; &rsqb;
</verb>
</p><p>
Data una lista, se ne possono accedere gli elementi separatamente o a gruppi,
 con i costrutti di indexing e slicing. L'indexing si ottiene (come in molti
 altri linguaggi) giustapponendo l'indice fra parentesi quadre alla lista (il
 primo elemento ha indice <tt>0</tt>): 
</p>
<p>
<verb>
&gt;&gt;&gt; print name&lsqb;1&rsqb;,name&lsqb;0&rsqb;
John Cleese
&gt;&gt;&gt; name&lsqb;0&rsqb; = &quot;Smith&quot;
</verb>
</p><p>
Lo slicing (alla lettera, <em>affettamento</em>) é quasi come l'indexing, eccetto
 che si scrivono sia l'indice iniziale sia quello finale del risultato, con
 un carattere di due-punti (&quot;<tt>:</tt>&quot;) per separarli: 
</p>
<p>
<verb>
&gt;&gt;&gt; x=&lsqb;'spam','spam','spam','spam','spam','eggs','and','spam'&rsqb;
&gt;&gt;&gt; print x&lsqb;5:7&rsqb;
&lsqb;'eggs','and'&rsqb;
</verb>
</p><p>
Notiamo che la fine é non-compresa. Se manca uno degli indici nello slicing,
 si prende "tutto in quella direzione". Ad esempio, <tt>list&lsqb;:3&rsqb;</tt> significa
 &quot;ogni elemento dall'inizio di list sino all'elemento 3, non compreso&quot;,
 cioè i primi 3 elementi, esattamente come <tt>list&lsqb;0:3&rsqb;</tt>. Invece, <tt>list&lsqb;3:&rsqb;</tt>
 significa &quot;ogni elemento di <tt>list</tt> a partire dall'elemento 3 (compreso)
 sino all'ultimo (compreso)&quot;. 
</p>
<p>
Sia nell'indexing, sia nello slicing, si possono usare anche indici negativi,
 che indicano di "contare dalla fine" : <tt>list&lsqb;-3&rsqb;</tt>, ad esempio, indica
 il terzo elemento dalla fine della lista.
</p>
<p>
Si puó anche assegnare una lista di qualsiasi lunghezza ad una slice di
 una lista: 
</p>
<p>
<verb>
y = &lsqb;&quot;fee&quot;,&quot;fie&quot;,&quot;foo&quot;,&quot;fum&quot;&rsqb; 
y&lsqb;1:-1&rsqb; = &lsqb;&quot;bar&quot;,&quot;baz&quot;,&quot;bat&quot;&rsqb; 
</verb>
</p><p>
mette in <tt>y</tt> la lista <tt>&lsqb;'fee', 'bar', 'baz', 'bat', 'fum'&rsqb;</tt>: infatti,
 la &quot;slice&quot; escludeva solo il primo e l'ultimo elemento (quindi, si
 trattava dei due elementi <tt>&quot;fie&quot;</tt> e <tt>&quot;foo&quot;</tt>), ed é stata sostituita,
 dall'istruzione di assegnamento, con i tre elementi elencati. La funzione intrinseca
 <tt>len</tt> dà la lunghezza di una lista; ad esempio, per qualsiasi lista <tt>a</tt>, <tt>a&lsqb;len(a)-1&rsqb;</tt>
 é sempre esattamente equivalente ad <tt>a&lsqb;-1&rsqb;</tt> (l'ultimo elemento della
 lista).
</p>
<p>
Tutto questo funziona anche con le stringhe:
</p>
<p>
<verb>
s=&quot;internazionalizzazione&quot; 
print s&lsqb;5:7&rsqb; &num; emette la stringa &quot;na&quot; 
</verb>
</p><p>
eccetto che, per le stringhe, non si possono fare assegnamenti ai risultati
 di slicing e indexing, perché le stringhe, a differenza delle liste, sono <em>immutabili</em>.
 Le liste hanno anche altri metodi di mutazione (non applicabili alle stringhe,
 per la stessa ragione), come <tt>mylist.append(value)</tt>, che aggiunge un valore alla
 fine della lista (allungandola quindi di un elemento), e <tt>mylist.sort()</tt>, che
 permuta gli elementi della lista per assicurare che essa sia ordinata. Le liste
 (e le stringhe) possono essere concatenate usando l'operatore <tt>+</tt>, e replicate
 un certo numero di volte usando l'operatore <tt>*</tt>:
</p>
<p>
<verb>
l = &lsqb;'a', 'b'&rsqb; + &lsqb;'c', 'd'&rsqb; * 3 
&num; l diventa &lsqb;'a','b','c','d','c','d','c','d'&rsqb;
</verb>
</p><sect>
Dizionari
<p>
I dizionari sono simili alle liste, ma i loro contenuti non sono in sequenza.
 Per indicizzarli, si usa invece il fatto che ogni elemento é associato a una
 chiave, o &quot;nome&quot;, che viene usato per reperire l'elemento, proprio
 come in un vero dizionario. Un paio di esempi: 
</p>
<p>
<verb>
telefoni = &lcub;&quot;Alice&quot;:23452532,&quot;Boris&quot;:252336,&quot;Clarice&quot;:2352525,&quot;Doris&quot;:23624643&rcub; 
persona = &lcub;'nome':&quot;Robin&quot;,'cognome':&quot;Hood&quot;,'professione':&quot;Fuorilegge&quot;&rcub;
</verb>
</p><p>
Per avere la professione della persona, useremo l'espressione <tt>persona&lsqb;&quot;professione&quot;&rsqb;</tt>.
 Per cambiare il cognome, potremmo scrivere: 
</p>
<p>
<verb>
persona&lsqb;'cognome'&rsqb; = &quot;di Locksley&quot; 
</verb>
</p><p>
e, identicamente, per aggiungere al dizionario un elemento non già presente:
 
</p>
<p>
<verb>
persona&lsqb;'specialità'&rsqb; = &quot;Arciere&quot; 
</verb>
</p><p>
Piuttosto semplice. Notiamo che, come le liste, i dizionari possono contenere
 altri dizionari (o liste -- e naturalmente, anche le liste possono contenere
 dizionari; si possono facilmente comporre strutture dati piuttosto avanzate).
 A partire da un dizionario <tt>dict</tt>, si può avere la sequenza delle sue chiavi
 (ad esempio, per iterarci con un for) chiamando <tt>dict.keys()</tt>: 
</p>
<p>
<verb>
for key in dict.keys(): 
    print key,dict&lsqb;key&rsqb; 
</verb>
</p><p>
Questo é un idioma molto comune, quindi c'é un'alternativa:
</p>
<p>
<verb>
for key,value in dict.items(): 
    print key,value
</verb>
</p><p>
Questo svolge lo stesso compito, poichè <tt>dict.items()</tt> restituisce una lista
 di coppie chiave/valore. Inoltre, <tt>dict.values()</tt> restituisce la lista dei valori
 (comodo se non interessano le relative chiavi); <tt>dict.has_key(key)</tt> restituisce
 un valore vero se la chiave é fra quelle attualmente presenti nel dizionario,
 altrimenti un valore falso.
</p>
<p>
L'operatore di formato, <tt>&percnt;</tt>, può accettare un dizionario come argomento
 di destra, e in questo caso la stringa di formato comprenderà anche i nomi
 (chiavi nel dizionario) da usare:
</p>
<p>
<verb>
&gt;&gt;&gt; &quot;&percnt;(nome)s &percnt;(cognome)s é un &percnt;(professione)s&quot; &percnt; persona
'Robin Hood é un Fuorilegge'
</verb>
</p><p>
La funzione intrinseca <tt>locals()</tt> restituisce un dizionario le cui coppie
 chiave/valore sono i nomi e i valori delle variabili locali, e similmente <tt>globals()</tt>,
 mentre <tt>vars()</tt> li fonde entrambi (con priorità alle variabili locali in caso
 di sovrapposizione, che é la normale &lsqb;e piuttosto intuitiva...&rsqb; regola
 del Python); sono molto comodi, ad esempio, per l'uso con l'operatore di formato
 <tt>&percnt;</tt>, per ottenere l'effetto della cosiddetta <em>interpolazione di variabili</em>
 di altri linguaggi (con un controllo assai piú preciso di quello permesso da
 questi altri linguaggi): 
</p>
<p>
<verb>
&quot;x=&percnt;(x)s, y=&percnt;(y)s, e z= &percnt;(z)s&quot; &percnt; vars()
</verb>
</p><p>
é un modo comodo di emettere i valori attuali delle variabili x, y e z,
 ciascuno con la propria identificazione.
</p>
<sect>
Stringhe
<p>
Abbiamo già usato sin dall'inizio le stringhe di Python, che in effetti
 si prestano ad un uso elementare assai intuitivo, ma é il caso di notare che,
 come un po' tutto in Python, anche le stringhe sono oggetti, dotate dei loro
 metodi; ad esempio, come già accennato, possono sempre essere usate come sequenze
 (immutabili) di caratteri, con indexing e slicing, uso in for, ecc. Hanno inoltre
 metodi particolari come <tt>lower</tt> (che restituisce la versione in minuscole della
 stringa) e <tt>split</tt> (che restituisce la lista delle varie parole presenti nella
 stringa, nell'ordine).
</p>
<p>
Per esempio, creiamo un <em>indice analitico</em> per un grosso file di testo <tt>big.txt</tt>:
 una lista alfabetica delle parole che contiene, una per riga, ciascuna seguita
 dai numeri delle righe in cui si trova. 
</p>
<p>
<verb>
fin=open(&quot;big.txt&quot;)
numero_riga=0
indice=&lcub; &rcub; &num; un dizionario vuoto
while 1:
    &num; ciclo input primario (righe in ingresso)
    riga=fin.readline()
    if not riga:
        break
    numero_riga=numero_riga+1
    parole=riga.lower().split() &num; lista delle parole, in minuscolo 
    for parola in parole:
        &num; ciclo input secondario (parole della riga) 
        if indice.has_key(parola): 
            indice&lsqb;parola&rsqb;.append(numero_riga) &num; aggiunge 1 elemento 
        else: 
            indice&lsqb;parola&rsqb;=&lsqb;numero_riga&rsqb; &num; lista di 1 solo elemento
parole=indice.keys() 
parole.sort() 
for parola in parole:
    &num; ciclo output primario (sulle parole riscontrate) 
    print parola,&quot;: &quot;,
    for numero_riga in indice&lsqb;parola&rsqb;: 
        &num; ciclo output secondario (numeri riga) 
        print numero_riga,
    print 
</verb>
</p><p>
L'istruzione <tt>print</tt> normalmente termina la riga di testo che emette, ma
 qui la usiamo con una virgola alla fine, il che elimina questa caratteristica
 e richiede invece un separatore &quot;spazio&quot;; in questo modo, la parola
 e i numeri delle righe che la contengono vengono emessi sulla stessa riga,
 separati da spazi.
</p>
<sect>
Moduli
<p>
Python offre una discreta funzionalità attraverso caratteristiche intrinseche
 (tipi di dati, operatori, funzioni), ma la maggior parte della sua potenza
 è messa a disposizione dai moduli -- pacchetti separati di funzionalità, che
 vanno esplicitamente importati alla bisogna. I moduli a loro volta possono
 essere intrinseci (Python ne ha parecchi), possono essere file scritti da noi
 (qualsiasi file <tt>.py</tt> può essere importato come modulo, e si possono anche scrivere
 altri moduli in C o C++), o li si può ottenere da terze parti ed installarseli
 (c'è un enorme numero di meravigliosi moduli Python disponibili per il download
 gratuito dalla rete, naturalmente).
</p>
<p>
Per esempio, un modulo intrinseco che potrebbe fare comodo per lo stesso
 compito del paragrafo precedente è <tt>fileinput</tt>, che permette di leggere uno o
 piú file di testo in sequenza, tenendo conto del numero di linea e con varie
 piccole comodità. Usandolo, il ciclo principale diventa assai piú semplice
 (visto che sfruttiamo la possibilità di iterare con <tt>for</tt>, e la funzione <tt>lineno()</tt>
 che tiene già traccia del numero progressivo di riga):
</p>
<p>
<verb>
import fileinput
filein=fileinput.input(&quot;big.txt&quot;)
indice=&lcub; &rcub;
&num; un dizionario vuoto
for riga in filein:
    &num; ciclo input primario (righe in ingresso) 
    parole=riga.lower().split()  &num; lista delle parole, in minuscolo 
    for parola in parole:
        &num; ciclo input secondario (parole della riga) 
        if indice.has_key(parola): 
            indice&lsqb;parola&rsqb;.append(filein.lineno()) &num; aggiunge un elemento
        else: 
            indice&lsqb;parola&rsqb;=&lsqb;filein.lineno()&rsqb; &num; lista di 1 solo elemento
</verb>
</p><p>
seguito, naturalmente, dallo stesso ciclo di uscita già usato all'esempio
 precedente. Le ultime quattro righe si potrebbero, alternativamente, riassumere
 in una sola, usando un metodo piú avanzato dell'oggetto-dizionario cui fa riferimento
 la variabile indice :
</p>
<p>
<verb>
indice.setdefault(parola,&lsqb;&rsqb;).append(filein.lineno())
</verb>
</p><p>
Python lascia queste scelte di stile (concisione e massima potenza, ovvero
 espressione dettagliata di massima semplicità elementare) all'apprezzamento
 del programmatore!
</p>
<sect>
Funzioni
<p>
Per costruire dei moduli (e non solo per questo), abbiamo chiaramente bisogno
 di definire noi stessi delle funzioni (o procedure che dir si voglia), cioè
 dei brani di codice, con un nome, che possono essere chiamati con dei parametri.
 A questo scopo Python utilizza la parola-chiave <tt>def</tt>: 
</p>
<p>
<verb>
def quadrato(x): 
    return x*x
print quadrato(2) 
&num; Emette 4 
</verb>
</p><p>
La parola-chiave <tt>return</tt> termina l'esecuzione della funzione, e ritorna
 come suo risultato il valore dell'espressione passatale (in mancanza, il valore
 speciale <tt>None</tt>, che è l'<em>oggetto nullo</em> del Python).
</p>
<p>
Se scriviamo queste due righe che definiscono la funzione quadrato in un
 file di testo chiamato <tt>matematica.py</tt> (e lo poniamo nel directory corrente,
 o in un directory elencato nella variabile d'ambiente <tt>PYTHONPATH</tt>), da qualsiasi
 altro programma Python potremo poi scrivere: 
</p>
<p>
<verb>
import matematica
print matematica.quadrato(2) 
&num; Emette 4
</verb>
</p><p>
oppure, se vogliamo incorporare solo le funzioni del modulo (non il modulo):
</p>
<p>
<verb>
from matematica import *
print quadrato(2) 
&num; Emette 4
</verb>
</p><p>
Tutti i parametri in Python sono passati <em>per riferimento</em> (come, ad esempio,
 in Java, e per ragioni simili, cioè che tutto funziona per riferimento in Python,
 come in Java; ci torneremo piú avanti) e possono avere valori di default (come
 in C++, ma anche con un nome, come in Visual Basic): 
</p>
<p>
<verb>
def cat(s1, s2, rep1=1, rep2=1): 
    return s1*rep1+s2*rep2

cat('fee','fie')
&num; ok, vale 'feefie' -- rep1 e rep2 entrambi da default 

cat('fee')
&num; errore -- s2 non ha default, quindi è obbligatorio 

cat('foo','bar',3) 
&num; restituisce 'foofoofoobar' 

cat('foo','bar',rep2=3) 
&num; restituisce 'foobarbarbar'
</verb>
</p><p>
Per chiamare una funzione, anche senza argomenti, bisogna sempre usare
 le parentesi, perchè se una funzione è nominata senza parentesi, si ha come
 risultato la funzione stessa; le funzioni sono valori di prima classe in Python...!
 Possiamo avere liste o dizionari contenenti funzioni, passare funzioni come
 argomenti e restituirle come risultati di altre funzioni, e anche semplicemente
 definire e usare dei sinonimi per esse, come ad esempio: 
</p>
<p>
<verb>
join=cat  &num; join diventa un &quot;sinonimo&quot; della funzione cat
join('a','b',3,2)
&num; restituisce 'aaabb'
</verb>
</p><sect>
Oggetti e riferimenti
<p>
Abbiamo già usato gli oggetti, piú che altro perchè ogni elemento di dati
 in Python è un oggetto... oltre ad avere (o <em>essere</em>) dati, ha dei metodi --
 funzioni che si possono chiamare con la sintassi, tipica appunto della <em>programmazione
 ad oggetti</em>, <tt>oggetto.funzione(argomenti)</tt>. 
</p>
<p>
Per esempio, abbiamo già visto che, data una lista in una variabile denominata
 <tt>L</tt>, chiamare <tt>L.sort()</tt> modifica la lista cosí che divenga ordinata; dato un dizionario
 in una variabile denominata <tt>D</tt>, chiamare <tt>D.values()</tt> restituisce una lista dei
 valori attualmente contenuti nel dizionario; e cosí via. Inoltre, parlando
 di I/O, abbiamo nominato la funzione intrinseca <tt>open</tt>, che ritorna un oggetto
 <em>file</em>, su cui possiamo chiamare metodi come <tt>readline</tt> e <tt>write</tt>.
</p>
<p>
Naturalmente, Python ci permette di creare dei nostri oggetti e determinare
 i loro metodi; linguaggio <em>profondamente ad oggetti</em>, ci mancherebbe altro che
 non rendesse perfettamente agevole definirne dei nuovi! Ma in questo articolo,
 per mancanza di spazio, non parleremo della facilità con cui Python permette
 di svolgere questi compiti; ci sono aspetti che vanno ben capiti prima di indirizzarsi
 a questi, e, in particolare, dobbiamo chiarire il concetto di <em>riferimento</em>.
 Ogni variabile Python, in qualsiasi momento, contiene un riferimento a un qualche
 oggetto; cosí pure ogni elemento di una lista, e ogni chiave e ogni valore
 di un dizionario. Spesso, questo aspetto non ha importanza, perchè il riferimento
 è a un oggetto immutabile -- qualsiasi numero è immutabile, e cosí pure qualsiasi
 stringa (le chiavi di un dizionario, in particolare, devono essere riferimenti
 a oggetti immutabili -- a questo scopo, c'è anche una specie di <em>lista immutabile</em>,
 detta <tt>tuple</tt>, che, sintatticamente, differisce dalla lista quasi solo nel fatto
 che le costanti che sono <tt>tuple</tt> si scrivono con parentesi tonde, invece delle
 parentesi quadre che sono usate per le costanti che sono liste). Ma, se abbiamo
 riferimenti a un oggetto mutabile, allora, se l'oggetto cambia, tutti i riferimenti
 implicitamente indicano il nuovo oggetto dopo il cambiamento: 
</p>
<p>
<verb>
&gt;&gt;&gt; x=&lsqb;'a','b','c'&rsqb; 
&gt;&gt;&gt; y=x 
&gt;&gt;&gt; x&lsqb;1&rsqb;='r' 
&gt;&gt;&gt; print y 
&lsqb;'a','r','c'&rsqb; 
</verb>
</p><p>
<tt>y</tt> si riferisce allo stesso oggetto cui si riferisce <tt>x</tt>, e questo oggetto
 è cambiato. Questo è spesso ciò che si desidera; quando non lo è, invece di
 aggiungere semplicemente un riferimento, come fa l'istruzione di assegnamento
 <tt>y=x</tt>, dobbiamo fare una copia, per esempio cambiando l'istruzione di assegnamento
 a: 
</p>
<p>
<verb>
y=x&lsqb;:&rsqb;
</verb>
</p><p>
Questo idioma di <em>slice dall'inizio alla fine</em> genera un nuovo oggetto, una
 copia di quello cui fa riferimento <tt>x</tt>, ed è alla copia che fa riferimento <tt>y</tt>.
 Di conseguenza, futuri cambiamenti della lista cui fa riferimento <tt>x</tt> non avranno
 nessun effetto sull'oggetto cui fa riferimento <tt>y</tt>, e viceversa.
</p>
<p>
Python fornisce anche un comodo modulo <tt>copy</tt> che gestisce per noi queste
 considerazioni: 
</p>
<p>
<verb>
import copy 
y=copy.copy(x) 
</verb>
</p><p>
esegue un'operazione simile a y=x&lsqb;:&rsqb;, ma lo fa polimorficamente
 (cioè, a qualsiasi cosa <tt>x</tt> faccia riferimento, che sia una lista, un dizionario,
 una stringa, una tupla, ...) cosí che noi non dobbiamo preoccuparci dei dettagli;
 e <tt>y=copy.deepcopy(x)</tt> si spinge anche piú a fondo, copiando ricorsivamente anche
 ciò a cui gli elementi di <tt>x</tt> fanno a loro volta riferimento.
</p>
<sect>
Altri tipi intrinseci
<p>
Oltre a numeri (interi e reali), stringhe, liste, dizionari, funzioni,
 e vari altri tipi la cui esistenza è stata già implicata (come gli oggetti-file
 restituiti dalla funzione <tt>open</tt>), Python offre vari altri tipi intrinseci, comodi
 e potenti nelle applicazioni in cui servono.
</p>
<p>
Ad esempio, i numeri complessi, indicati posponendo una <tt>j</tt> alla loro parte
 immaginaria: 
</p>
<p>
<verb>
&gt;&gt;&gt; x=2+2j 
&gt;&gt;&gt; x*(1-1j) 
(4+0j) 
&gt;&gt;&gt; x.real 
2.0 
&gt;&gt;&gt; x.imag 
2.0 
</verb>
</p><p>
col relativo complemento di funzioni matematiche, ottenute con <tt>import cmath</tt>
 cosí come quelle sui numeri reali si ottengono con <tt>import math</tt>: 
</p>
<p>
<verb>
&gt;&gt;&gt; import cmath
&gt;&gt;&gt; cmath.sqrt(-1)
1j
&gt;&gt;&gt; cmath.sin(1j)
1.17520119364j 
</verb>
</p><p>
I numeri complessi, naturalmente, sono utili solo per certi particolari
 compiti matematici.
</p>
<p>
Per altri compiti, come quelli di aritmetica combinatoria, tornano invece
 utili gli interi <em>lunghi</em> (cioè con precisione illimitata), indicati posponendo
 una <tt>L</tt> alle loro cifre...: 
</p>
<p>
<verb>
def fact(x):
    if x&lt;=1:
        return 1L 
    else: 
        return x*fact(x-1) 
</verb>
</p><p>
Questo ci permette di calcolare facilmente in quanti diversi modi può essere
 mescolato un normale mazzo di carte: 
</p>
<p>
<verb>
&gt;&gt;&gt; fact(52)
80658175170943878571660636856403766975289505440883277824000000000000L
</verb>
</p><p>
o quale sia la probabilità, ad esempio, che una mano di 13 carte (su 52)
 abbia esattamente cinque carte di picche (sulle 13 picche del mazzo): 
</p>
<p>
<verb>
def comb(m,n): 
    return fact(m)/(fact(n)*fact(m-n))

&gt;&gt;&gt; comb(52,13) 
635013559600L
</verb>
</p><p>
questo è il numero di diverse mani di 13 carte su 52,
</p>
<p>
<verb>
&gt;&gt;&gt; comb(13,5)*comb(39,8)
79181063676L
</verb>
</p><p>
questo è il numero di mani con esattamente 5 picche e 8 non-picche,
</p>
<p>
<verb>
&gt;&gt;&gt; comb(13,5)*comb(39,8)/float(comb(52,13))
0.12469192583206691
</verb>
</p><p>
e quindi questa è la probabilità che cercavamo (circa il 12.47&percnt;).
</p>
<p>
Utili per scopi di &quot;internazionalizzazione&quot; dei programmi sono
 le stringhe Unicode, con gli stessi metodi delle stringhe &quot;normali&quot;
 e un'amplissima gamma di codifica/decodifica:
</p>
<p>
<verb>
&gt;&gt;&gt; u&quot;Cioé&quot;.encode(&quot;iso-8859-1&quot;) 
'Cio&bsol;351' 
&gt;&gt;&gt; u&quot;Cioè&quot;.encode(&quot;utf-8&quot;) 
'Cio&bsol;303&bsol;251'
</verb>
</p><p>
Gli altri tipi intrinseci sono forniti da moduli pure intrinseci, tramite
 un esplicito <tt>import</tt>; gli esempi sono numerosi, come le regular expressions
 nel modulo <tt>re</tt>, gli array nel modulo <tt>array</tt>, gli interpreti interattivi nel modulo
 <tt>cmd</tt>, ecc.
</p>


</article>
