Sei sulla pagina 1di 12

Python: facile, pulito, potente

Magnus Lie Hetland e Alex Martelli

Cos' Python?

Python un linguaggio interpretato, interattivo, orientato agli oggetti; pu essere, per vari aspetti, paragonato a linguaggi come Tcl, Perl, e Java.
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).
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.
Vari siti Web come <http://www.python.org>, <http://www.pythonware.com/daily/>, <http://www.
vex.net/~x/parnassus/> (e, in italiano, il sito <http://web.tiscalinet.it/python>) contengono molto
materiale utile sul linguaggio, e una dovizia di puntatori ad altri materiali.

Interpretato o compilato?

Python, come Java o Perl, in realt entrambe le cose  sia compilato, sia interpretato.
Il compilatore Python trasforma il testo (codice sorgente) dei nostri programmi in un codice intermedio,
detto byte-code, che pu essere visto come "codice-macchina" per una macchina "virtuale" 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 dierenza che in Java, si pu richiedere direttamente l'esecuzione
dei le-sorgente (normalmente con estensione .py), senza necessit di un esplicito passaggio di compilazione;
come in Java, e a dierenza che in Perl, il byte-code non viene solo preparato "al volo" 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 le sorgente pi aggiornato di quello
contenente il byte-code).
Esistono compilatori Python che producono codice per altre macchine virtuali: Jython produce bytecode per
una JVM (le .class), Python.NET produce il codice-intermedio MSIL tipico della nuova piattaforma .NET
(le .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 dieriscano molto!).

Per cosa si usa Python?

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

Da dove comincio?

4.

FastCGI, mod_python, etc; client-side, "entro il browser", opzione per cui Python ore 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).
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 scientico), e, facilmente incorporato in applicazioni (magari
ricche e complesse), per la personalizzazione e automatizzazione delle applicazioni stesse.
Ma, per Python, questo solo l'inizio.
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, <http://www.zope.org>,
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, ...).
Sempre a titolo di esempio, segnaliamo anche un semplice DBMS relazionale SQL (transazionale, con la
possibilit di uso client/server in TCP/IP), Gady , interamente scritto in Python  vedi <http://www.
chordate.com/kwParsing/gadfly.html> (le sue prestazioni su database grossi possono essere sostanzialmente 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 colli di
bottiglia computazionali, un'ultima ottimizzazione pu compiersi codicando in C o C++ i bassissimi livelli
di questi colli di bottiglia). Anche Gady liberamente e gratuitamente scaricabile ed utilizzabile, secondo
il modello Open Source.

Da dove comincio?

Scarica e installa l'ultima versione di Python dal sito <http://www.python.org/> 1 (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 PATH
(automatico se installi da RPM). Hai ora a disposizione un ambiente integrato di sviluppo (si chiama idle,
e comprende editor specializzato, interprete interattivo, debugger, class browser, documentazione...) e un
pi semplice programma chiamato python, meno ricco e potente ma pi facile da imparare ad usare  ci
concentriamo su quest'ultimo, ma conviene sicuramente anche esplorare idle, che alla lunga pu orire
notevoli comodit. Eseguendo python senza argomenti da qualsiasi shell, otterrai una risposta del tipo:

Python 2.0b2 (#6, Sep 26 2000, 14:59:21) [gcc 2.9.37 (Intel)] on linux
Type "copyright", "credits" or "license" for more information.
>>>
e puoi immettere interattivamente codice Python al prompt '>>>'  verr eseguito immediatamente, il che
comodo per provare. Ad esempio, immettendo la riga di codice:

print "Hello, world!"


il messaggio verr visualizzato. Alla ne, premerai Ctrl-D per terminare la sessione interattiva di Python.
Per programmare "davvero", scriverai il codice Python, con qualsiasi editor di testi (ad esempio, vim), in
un le di testo (chiamato, ad esempio, hello.py), e lo eseguirai (da una shell) col comando:
1

Gli esempi che seguono si riferiscono a Python versione 2.0 o superiore.

5.

Com' fatto Python?

python hello.py
se hello.py contiene la stessa, unica riga print "Hello, world!", anche questo mostrer lo stesso messaggio. Esistono inoltre altri modi di rendere direttamente eseguibile un le di testo contenente un programma
(script ) Python: su Linux, basta renderlo eseguibile con il comando chmod +x e assicurarsi che inizi con una
prima riga del tipo:

#!/usr/bin/env python
Il programma hello.py potr ora venire eseguito direttamente digitandone il nome (ed eventualmente il
directory, come per qualsiasi altro programma) da qualsiasi shell.

Com' fatto Python?

Python praticamente pseudo-codice eseguibile . 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 =
; l'eguaglianza si controlla con l'operatore ==. Si possono assegnare molteplici variabili simultaneamente:
 x,y,z = 1,2,3
 prima, seconda = seconda, prima
 a = b = 123
I blocchi sono indicati dall'indentazione, e solo dall'indentazione (niente BEGIN/END, niente parentesi grae).
Una struttura di controllo fondamentale if (questi due esempi sono equivalenti) :

if x < 5 or (x > 10 and x < 20):


print "Il valore OK." # qui siamo dentro il blocco if
# qui siamo fuori dal blocco if
if x < 5 or 10 < x < 20:
print " Il valore OK."
Ci sono poi i cicli:

for i in [1,2,3,4,5]:
print "Iterazione numero", i
x = 10
while x >= 0:
print "x non ancora negativo"
x = x-1
La variabile-indice del ciclo for itera sugli elementi di una lista (una costante lista pu essere scritta con
parentesi quadre e virgole, come nell'esempio). Per fare un "normale" ciclo di for (cio uno in cui la variabile
indice itera su di una sequenza di numeri), si pu usare la funzione intrinseca range():

# Stampa i numeri da 0 a 99 inclusi


for value in range(100):
print value

I/O in Python

6.

(La riga che inizia con # un commento, e viene quindi ignorata da Python). Attenzione: Python (come
Java, C, C++,...) case-sensitive  x e X sono due variabili dierenti... non un problema, ma attenzione
che questo non provochi errori!

I/O in Python

Quanto visto nora 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 input:

x = input("Immetti un numero: ")


print "Il quadrato di", x, "", x*x
La funzione input 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).
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 raw_input (per convertire una stringa s ad intero, si potr
poi usare int(s)). 2 Spesso si vogliono leggere e scrivere le di testo; anche questo facile  ad esempio,
per copiare "fin.txt" su "fou.txt" si pu scrivere (leggendo subito tutte le righe, poi eseguendo un ciclo
su tutto l'insieme delle righe lette):

fou=open("fou.txt","w")
for line in open("fin.txt").readlines():
fou.write(line)
In alternativa, e in modo del tutto equivalente, si pu leggere una sola riga alla volta:

fou=open("fou.txt","w")
fin=open("fin.txt","r")
while 1:
line = fin.readline()
if not line:
break
fou.write(line)
(break interrompe il ciclo corrente).
Il secondo argomento della funzione intrinseca open dice se stiamo aprendo il le in lettura o in scrittura;
facoltativo, e il default la lettura. readlines restituisce tutte le righe, in sequenza, pronte ad esempio per
un'interazione con for; readline (al singolare, cio senza la s nale) restituisce solo la prossima riga 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 le di testo oerta dal modulo fileinput, che illustreremo fra breve.
A volte, si vogliono formattare dei dati ottenendo una stringa (ad esempio per emetterla); questo si pu fare
con l'operatore %, che prende sulla sinistra una stringa di formato (molto simile alla stringa di formato di
una printf del C) e sulla destra una sequenza di valori, e restituisce una stringa. Ad esempio, per numerare
le righe emesse, il ciclo potrebbe essere modicato nel modo seguente :
2

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 dierenza).

7.

Liste

fou=open("fou.txt","w")
fin=open("fin.txt","r")
i=0
while 1:
line = fin.readline()
if not line:
break
i=i+1
fou.write("%d: %s" % i, line)

Liste

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:

name = ["Cleese", "John"]


x = [ [1,2,3], [y,z], [ [ [ ] ] ] ]
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 0):

>>> print name[1],name[0]


John Cleese
>>> name[0] = "Smith"
Lo slicing (alla lettera, aettamento ) quasi come l'indexing, eccetto che si scrivono sia l'indice iniziale sia
quello nale del risultato, con un carattere di due-punti (":") per separarli:

>>> x=['spam','spam','spam','spam','spam','eggs','and','spam']
>>> print x[5:7]
['eggs','and']
Notiamo che la ne non-compresa. Se manca uno degli indici nello slicing, si prende "tutto in quella
direzione". Ad esempio, list[:3] signica "ogni elemento dall'inizio di list sino all'elemento 3, non compreso", cio i primi 3 elementi, esattamente come list[0:3]. Invece, list[3:] signica "ogni elemento di
list a partire dall'elemento 3 (compreso) sino all'ultimo (compreso)".
Sia nell'indexing, sia nello slicing, si possono usare anche indici negativi, che indicano di "contare dalla ne"
: list[-3], ad esempio, indica il terzo elemento dalla ne della lista.
Si pu anche assegnare una lista di qualsiasi lunghezza ad una slice di una lista:

y = ["fee","fie","foo","fum"]
y[1:-1] = ["bar","baz","bat"]
mette in y la lista ['fee', 'bar', 'baz', 'bat', 'fum']: infatti, la "slice" escludeva solo il primo e
l'ultimo elemento (quindi, si trattava dei due elementi "fie" e "foo"), ed stata sostituita, dall'istruzione
di assegnamento, con i tre elementi elencati. La funzione intrinseca len d la lunghezza di una lista; ad

8.

Dizionari

esempio, per qualsiasi lista a, a[len(a)-1] sempre esattamente equivalente ad a[-1] (l'ultimo elemento
della lista).
Tutto questo funziona anche con le stringhe:

s="internazionalizzazione"
print s[5:7] # emette la stringa "na"
eccetto che, per le stringhe, non si possono fare assegnamenti ai risultati di slicing e indexing, perch le
stringhe, a dierenza delle liste, sono immutabili . Le liste hanno anche altri metodi di mutazione (non
applicabili alle stringhe, per la stessa ragione), come mylist.append(value), che aggiunge un valore alla
ne della lista (allungandola quindi di un elemento), e mylist.sort(), che permuta gli elementi della lista
per assicurare che essa sia ordinata. Le liste (e le stringhe) possono essere concatenate usando l'operatore +,
e replicate un certo numero di volte usando l'operatore *:

l = ['a', 'b'] + ['c', 'd'] * 3


# l diventa ['a','b','c','d','c','d','c','d']

Dizionari

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 "nome", che viene usato per reperire l'elemento, proprio
come in un vero dizionario. Un paio di esempi:

telefoni = {"Alice":23452532,"Boris":252336,"Clarice":2352525,"Doris":23624643}
persona = {'nome':"Robin",'cognome':"Hood",'professione':"Fuorilegge"}
Per avere la professione della persona, useremo l'espressione persona["professione"]. Per cambiare il
cognome, potremmo scrivere:

persona['cognome'] = "di Locksley"


e, identicamente, per aggiungere al dizionario un elemento non gi presente:

persona['specialit'] = "Arciere"
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 dict, si pu avere la sequenza delle sue chiavi (ad esempio,
per iterarci con un for) chiamando dict.keys():

for key in dict.keys():


print key,dict[key]
Questo un idioma molto comune, quindi c' un'alternativa:

for key,value in dict.items():


print key,value

9.

Stringhe

Questo svolge lo stesso compito, poich dict.items() restituisce una lista di coppie chiave/valore.
Inoltre, dict.values() restituisce la lista dei valori (comodo se non interessano le relative chiavi);
dict.has_key(key) restituisce un valore vero se la chiave fra quelle attualmente presenti nel dizionario,
altrimenti un valore falso.
L'operatore di formato, %, 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:

>>> "%(nome)s %(cognome)s un %(professione)s" % persona


'Robin Hood un Fuorilegge'
La funzione intrinseca locals() restituisce un dizionario le cui coppie chiave/valore sono i nomi e i valori delle
variabili locali, e similmente globals(), mentre vars() li fonde entrambi (con priorit alle variabili locali
in caso di sovrapposizione, che la normale [e piuttosto intuitiva...] regola del Python); sono molto comodi,
ad esempio, per l'uso con l'operatore di formato %, per ottenere l'eetto della cosiddetta interpolazione di
variabili di altri linguaggi (con un controllo assai pi preciso di quello permesso da questi altri linguaggi):

"x=%(x)s, y=%(y)s, e z= %(z)s" % vars()


un modo comodo di emettere i valori attuali delle variabili x, y e z, ciascuno con la propria identicazione.

Stringhe

Abbiamo gi usato sin dall'inizio le stringhe di Python, che in eetti 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 lower (che restituisce
la versione in minuscole della stringa) e split (che restituisce la lista delle varie parole presenti nella stringa,
nell'ordine).
Per esempio, creiamo un indice analitico per un grosso le di testo big.txt: una lista alfabetica delle parole
che contiene, una per riga, ciascuna seguita dai numeri delle righe in cui si trova.

fin=open("big.txt")
numero_riga=0
indice={ } # un dizionario vuoto
while 1:
# ciclo input primario (righe in ingresso)
riga=fin.readline()
if not riga:
break
numero_riga=numero_riga+1
parole=riga.lower().split() # lista delle parole, in minuscolo
for parola in parole:
# ciclo input secondario (parole della riga)
if indice.has_key(parola):
indice[parola].append(numero_riga) # aggiunge 1 elemento
else:
indice[parola]=[numero_riga] # lista di 1 solo elemento
parole=indice.keys()

10.

Moduli

parole.sort()
for parola in parole:
# ciclo output primario (sulle parole riscontrate)
print parola,": ",
for numero_riga in indice[parola]:
# ciclo output secondario (numeri riga)
print numero_riga,
print
L'istruzione print normalmente termina la riga di testo che emette, ma qui la usiamo con una virgola alla
ne, il che elimina questa caratteristica e richiede invece un separatore "spazio"; in questo modo, la parola
e i numeri delle righe che la contengono vengono emessi sulla stessa riga, separati da spazi.

10

Moduli

Python ore 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 le scritti da noi (qualsiasi le .py 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).
Per esempio, un modulo intrinseco che potrebbe fare comodo per lo stesso compito del paragrafo precedente
fileinput, che permette di leggere uno o pi le 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 for, e la funzione lineno() che tiene gi traccia del numero progressivo di riga):

import fileinput
filein=fileinput.input("big.txt")
indice={ }
# un dizionario vuoto
for riga in filein:
# ciclo input primario (righe in ingresso)
parole=riga.lower().split() # lista delle parole, in minuscolo
for parola in parole:
# ciclo input secondario (parole della riga)
if indice.has_key(parola):
indice[parola].append(filein.lineno()) # aggiunge un elemento
else:
indice[parola]=[filein.lineno()] # lista di 1 solo elemento
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 :

indice.setdefault(parola,[]).append(filein.lineno())
Python lascia queste scelte di stile (concisione e massima potenza, ovvero espressione dettagliata di massima
semplicit elementare) all'apprezzamento del programmatore!

11.

11

Funzioni

Funzioni

Per costruire dei moduli (e non solo per questo), abbiamo chiaramente bisogno di denire 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 def:

def quadrato(x):
return x*x
print quadrato(2)
# Emette 4
La parola-chiave return termina l'esecuzione della funzione, e ritorna come suo risultato il valore
dell'espressione passatale (in mancanza, il valore speciale None, che l'oggetto nullo del Python).
Se scriviamo queste due righe che deniscono la funzione quadrato in un le di testo chiamato matematica.py
(e lo poniamo nel directory corrente, o in un directory elencato nella variabile d'ambiente PYTHONPATH), da
qualsiasi altro programma Python potremo poi scrivere:

import matematica
print matematica.quadrato(2)
# Emette 4
oppure, se vogliamo incorporare solo le funzioni del modulo (non il modulo):

from matematica import *


print quadrato(2)
# Emette 4
Tutti i parametri in Python sono passati per riferimento (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):

def cat(s1, s2, rep1=1, rep2=1):


return s1*rep1+s2*rep2
cat('fee','fie')
# ok, vale 'feefie' -- rep1 e rep2 entrambi da default
cat('fee')
# errore -- s2 non ha default, quindi obbligatorio
cat('foo','bar',3)
# restituisce 'foofoofoobar'
cat('foo','bar',rep2=3)
# restituisce 'foobarbarbar'
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 denire e usare dei sinonimi per esse, come ad esempio:

12.

Oggetti e riferimenti

10

join=cat # join diventa un "sinonimo" della funzione cat


join('a','b',3,2)
# restituisce 'aaabb'

12

Oggetti e riferimenti

Abbiamo gi usato gli oggetti, pi che altro perch ogni elemento di dati in Python un oggetto... oltre ad
avere (o essere ) dati, ha dei metodi  funzioni che si possono chiamare con la sintassi, tipica appunto della
programmazione ad oggetti , oggetto.funzione(argomenti).
Per esempio, abbiamo gi visto che, data una lista in una variabile denominata L, chiamare L.sort() modica
la lista cos che divenga ordinata; dato un dizionario in una variabile denominata D, chiamare D.values()
restituisce una lista dei valori attualmente contenuti nel dizionario; e cos via. Inoltre, parlando di I/O,
abbiamo nominato la funzione intrinseca open, che ritorna un oggetto le , su cui possiamo chiamare metodi
come readline e write.
Naturalmente, Python ci permette di creare dei nostri oggetti e determinare i loro metodi; linguaggio profondamente ad oggetti , ci mancherebbe altro che non rendesse perfettamente agevole denirne 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 riferimento . 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 lista immutabile , detta tuple, che, sintatticamente, dierisce dalla lista quasi solo nel fatto che le costanti che sono tuple 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:

>>> x=['a','b','c']
>>> y=x
>>> x[1]='r'
>>> print y
['a','r','c']
y si riferisce allo stesso oggetto cui si riferisce x, 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 y=x, dobbiamo fare una copia, per esempio cambiando l'istruzione di assegnamento a:
y=x[:]
Questo idioma di slice dall'inizio alla ne genera un nuovo oggetto, una copia di quello cui fa riferimento x,
ed alla copia che fa riferimento y. Di conseguenza, futuri cambiamenti della lista cui fa riferimento x non
avranno nessun eetto sull'oggetto cui fa riferimento y, e viceversa.
Python fornisce anche un comodo modulo copy che gestisce per noi queste considerazioni:

import copy
y=copy.copy(x)

13.

Altri tipi intrinseci

11

esegue un'operazione simile a y=x[:], ma lo fa polimorcamente (cio, a qualsiasi cosa x faccia riferimento,
che sia una lista, un dizionario, una stringa, una tupla, ...) cos che noi non dobbiamo preoccuparci dei
dettagli; e y=copy.deepcopy(x) si spinge anche pi a fondo, copiando ricorsivamente anche ci a cui gli
elementi di x fanno a loro volta riferimento.

13

Altri tipi intrinseci

Oltre a numeri (interi e reali), stringhe, liste, dizionari, funzioni, e vari altri tipi la cui esistenza stata gi
implicata (come gli oggetti-le restituiti dalla funzione open), Python ore vari altri tipi intrinseci, comodi
e potenti nelle applicazioni in cui servono.
Ad esempio, i numeri complessi, indicati posponendo una j alla loro parte immaginaria:

>>> x=2+2j
>>> x*(1-1j)
(4+0j)
>>> x.real
2.0
>>> x.imag
2.0
col relativo complemento di funzioni matematiche, ottenute con import cmath cos come quelle sui numeri
reali si ottengono con import math:

>>> import cmath


>>> cmath.sqrt(-1)
1j
>>> cmath.sin(1j)
1.17520119364j
I numeri complessi, naturalmente, sono utili solo per certi particolari compiti matematici.
Per altri compiti, come quelli di aritmetica combinatoria, tornano invece utili gli interi
precisione illimitata), indicati posponendo una L alle loro cifre...:

lunghi (cio con

def fact(x):
if x<=1:
return 1L
else:
return x*fact(x-1)
Questo ci permette di calcolare facilmente in quanti diversi modi pu essere mescolato un normale mazzo di
carte:

>>> fact(52)
80658175170943878571660636856403766975289505440883277824000000000000L
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):

13.

Altri tipi intrinseci

12

def comb(m,n):
return fact(m)/(fact(n)*fact(m-n))
>>> comb(52,13)
635013559600L
questo il numero di diverse mani di 13 carte su 52,

>>> comb(13,5)*comb(39,8)
79181063676L
questo il numero di mani con esattamente 5 picche e 8 non-picche,

>>> comb(13,5)*comb(39,8)/float(comb(52,13))
0.12469192583206691
e quindi questa la probabilit che cercavamo (circa il 12.47%).
Utili per scopi di "internazionalizzazione" dei programmi sono le stringhe Unicode, con gli stessi metodi delle
stringhe "normali" e un'amplissima gamma di codica/decodica:

>>> u"Cio".encode("iso-8859-1")
'Cio\351'
>>> u"Cio".encode("utf-8")
'Cio\303\251'
Gli altri tipi intrinseci sono forniti da moduli pure intrinseci, tramite un esplicito import; gli esempi sono
numerosi, come le regular expressions nel modulo re, gli array nel modulo array, gli interpreti interattivi
nel modulo cmd, ecc.