Ci sono parecchi modi per mostrare l'output di un programma; i dati possono essere stampati in una forma leggibile, o scritti in un file per usi futuri. Questo capitolo tratterà alcune delle possibilità.
Fino a qui si sono visti due modi di scrivere valori: le
espressioni e l'istruzione print. Un terzo modo è
usare il metodo write() degli oggetti file; si può fare
riferimento al file di standard output come sys.stdout
. Si veda
la Libreria di riferimento per ulteriori informazioni.
Spesso si vorrà avere un controllo sulla formattazione dell'output che
vada aldilà dello stampare semplicemente dei valori separati da
spazi. Ci sono due modi per formattare l'output; il primo è fare da sé
tutto il lavoro di gestione delle stringhe; usando le operazioni di
affettamento e concatenamento si possono creare tutti i layout che si
vogliono. Il modulo standard string
contiene alcuni utili operatori di riempimento (NdT: padding) di
stringhe ad una colonna di ampiezza data; questi verranno trattati
brevemente. Il secondo modo è usare l'operatore %
con una
stringa come argomento a sinistra. %
interpreta l'argomento di
sinistra come una stringa di formato nello stile della funzione C
sprintf() che dev'essere applicata all'argomento a destra,
e restituisce la stringa risultante.
Beninteso, rimane un problema: come si fa a convertire valori in
stringhe? Fortunatamente, Python ha un modo per convertire un
qualsiasi valore in una stringa: lo si passa alla funzione
repr() o str(). Gli apici inversi (` `
)
sono equivalenti a repr(), ma l'uso di questa forma è
scoraggiato.
La funzione str() restituisce la rappresentazione del valore in termini umanamente comprensibili, mentre repr() genera la rappresentazione del valore comprensibile dall'interprete (o solleverà un'eccezione del tipo SyntaxError se questa non ha una sintassi equivalente). Per oggetti che non hanno una specifica rappresentazione in termini umanamente comprensibili, str() restituirà lo stesso valore di repr(). Molti valori, simili a quelli numerici o a strutture come liste e dizionari, hanno la stessa rappresentazione usando le due funzioni. Nello specifico, stringhe e numeri in virgola mobile, hanno due distinte rappresentazioni.
Alcuni esempi:
>>> s = 'Ciao, mondo.' >>> str(s) 'Ciao, mondo.' >>> repr(s) "'Ciao, mondo.'" >>> str(0.1) '0.1' >>> repr(0.1) '0.10000000000000001' >>> x = 10 * 3.25 >>> y = 200 * 200 >>> s = 'Il valore di x è ' + repr(x) + ' e y è ' + repr(y) + '...' >>> print s Il valore di x è 32.5 e y è 40000... >>> # repr() aggiunge gli apici di stringa e le barre rovesciate: ... ciao = 'ciao, mondo\n' >>> ciaos = repr(ciao) >>> print ciaos 'ciao, mondo\n' >>> # L'argomento di repr() può essere anche un oggetto Python: ... repr((x, y, ('spam', 'eggs'))) "(32.5, 40000, ('spam', 'eggs'))" >>> # Gli apici inversi possono essere convenienti in sessioni interattive: ... `x, y, ('spam', 'eggs')` "(32.5, 40000, ('spam', 'eggs'))"
Ecco due modi di scrivere una tabella di quadrati e cubi:
>>> for x in range(1, 11): ... print repr(x).rjust(2), repr(x*x).rjust(3), ... # Si noti la virgola in coda sulla riga precedente ... print repr(x*x*x).rjust(4) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000 >>> for x in range(1,11): ... print '%2d %3d %4d' % (x, x*x, x*x*x) ... 1 1 1 2 4 8 3 9 27 4 16 64 5 25 125 6 36 216 7 49 343 8 64 512 9 81 729 10 100 1000
Si noti che uno spazio fra le colonne è stato aggiunto per il modo in cui lavora print: viene sempre inserito uno spazio tra i suoi argomenti.
Questa è una dimostrazione del metodo rjust() di oggetti stringa, che giustifica a destra una stringa in un campo di ampiezza data, riempiendola di spazi a sinistra. Questo metodo non scrive niente ma restituisce una nuova stringa. Se la stringa di input è troppo lunga non viene troncata ma restituita intatta; questo potrebbe scombussolare l'allineamento delle colonne desiderato, ma di solito questo è preferibile all'alternativa, cioè riportare un valore menzognero. Se davvero si desidera il troncamento si può sempre aggiungere un'operazione di affettamento, come in "x.ljust( n)[:n]".
C'è un'altro metodo, zfill(), che aggiunge ad una stringa numerica degli zero a sinistra. Tiene conto dei segni più e meno:
>>> '12'.zfill(5) '00012' +>>> '-3.14'.zfill(7) '-003.14' >>> '3.14159265359'.zfill(5) '3.14159265359'
L'uso dell'operatore %
è il seguente:
>>> import math >>> print 'Il valore di PI è approssimativamente %5.3f.' % math.pi Il valore di PI è approssimativamente 3.142.
Se c'è più di un codice di formato nella stringa, si passi una tupla come operando di destra, a esempio:
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 7678} >>> for nome, telefono in table.items(): ... print '%-10s ==> %10d' % (nome, telefono) ... Jack ==> 4098 Dcab ==> 7678 Sjoerd ==> 4127
La maggior parte dei codici di formato funziona esattamente come in C
e richiede che venga passato il tipo appropriato; comunque, nel caso
non lo sia, si ottiene un'eccezione, non un core dump. Il codice di
formato %s
ha un comportamento più rilassato: se l'argomento
corrispondente non è un oggetto stringa, viene convertito in stringa
tramite la funzione built-in str(). L'uso di *
per
passare l'ampiezza o la precisione come argomento separato (numero
intero) è supportato, mentre i codici di formato C %n
e
%p
non sono supportati.
Nel caso si abbia una stringa di formato davvero lunga che non si
vuole suddividere in parti, sarebbe carino poter fare riferimento alle
variabili da formattare tramite il nome piuttosto che tramite la
posizione. Ciò può essere ottenuto usando la forma
%(nome)formato
, p.e.
>>> table = {'Sjoerd': 4127, 'Jack': 4098, 'Dcab': 8637678} >>> print 'Jack: %(Jack)d; Sjoerd: %(Sjoerd)d; Dcab: %(Dcab)d' % table Jack: 4098; Sjoerd: 4127; Dcab: 8637678
È particolarmente utile in combinazione con la nuova funzione built-in vars(), che restituisce un dizionario contenente tutte le variabili locali.
open() restituisce un oggetto file, ed è perlopiù usata con due argomenti: "open(nomefile, modo)".
>>> f=open('/tmp/workfile', 'w') >>> print f <open file '/tmp/workfile', mode 'w' at 80a0960>
Il primo argomento è una stringa contenente il nome del file. Il
secondo è un'altra stringa contenente pochi caratteri che descrivono
il modo nel quale verrà usato il file. modo sarà 'r'
(`read') quando il file verrà solamente letto, 'w'
per la sola
scrittura (`write'), in caso esista già un file con lo stesso nome,
esso verrà cancellato, mentre 'a'
aprirà il file in
``aggiunta'' (`append'): qualsiasi dato scritto sul file verrà
automaticamente aggiunto alla fine dello stesso. 'r+'
aprirà il
file sia in lettura che in scrittura. L'argomento modo è
facoltativo; in caso di omissione verrà assunto essere 'r'
.
Su Windows e Macintosh, 'b'
aggiunto al modo apre il file in
modo binario, per cui ci sono ulteriori modi come 'rb'
,
'wb'
e 'r+b'
. Windows distingue tra file di testo e
binari; i caratteri EOF dei file di testo vengono leggermente alterati
in automatico quando i dati vengono letti o scritti. Questa modifica
che avviene di nascosto ai dati dei file è adatta ai file di testo
ASCII, ma corromperà i dati binari presenti ad esempio in file JPEG o
.EXE. Si raccomanda cautela nell'uso del modo binario quando si
sta leggendo o scrivendo su questi tipi di file. Si noti che l'esatta
semantica del modo testo su Macintosh dipende dalla libreria C
usata.
Nel resto degli esempi di questa sezione si assumerà che sia già stato
creato un oggetto file chiamato f
.
Per leggere i contenuti di un file, s'invochi
f.read(lunghezza)
, che legge una certa quantità di dati e
li restituisce come stringa. lunghezza è un argomento numerico
facoltativo. Se omesso o negativo, verrà letto e restituito l'intero
contenuto del file. Se il file è troppo grosso rispetto alla memoria
della macchina il problema è tutto vostro. Altrimenti viene letto e
restituito al più un numero di byte pari a lunghezza. Se è stata
raggiunta la fine del file, f.read()
restituirà una stringa
vuota (""
).
>>> f.read() 'Questo è l'intero file.\n' >>> f.read() ''
f.readline()
legge una singola riga dal file; un carattere di
fine riga (\n
) viene lasciato alla fine della stringa, e
viene omesso solo nell'ultima riga del file nel caso non finisca
con un fine riga. Ciò rende il valore restituito non ambiguo: se
f.readline()
restituisce una stringa vuota, è stata raggiunta
la fine del file, mentre una riga vuota è rappresentata da
'\n'
, stringa che contiene solo un singolo carattere di
fine riga.
>>> f.readline() 'Questa è la prima riga del file.\n' >>> f.readline() 'Seconda riga del file\n' >>> f.readline() ''
f.readlines()
restituisce una lista contenente tutte le righe
di dati presenti nel file. Se le viene passato un parametro facoltativo
lunghezza_suggerita, legge tale numero di byte dal file, poi
continua fino alla fine della riga e restituisce le righe. Viene
spesso usata per consentire la lettura efficiente per righe di un
file, senza dover caricare l'intero file in memoria. Verranno
restituite solo righe complete.
>>> f.readlines() ['Questa è la prima riga del file.\n', 'Seconda riga del file\n']
f.write(stringa)
scrive il contenuto di stringa nel
file, restituendo None
.
>>> f.write('Questo è un test\n')
f.tell()
restituisce un intero che fornisce la posizione nel
file dell'oggetto file, misurata in byte dall'inizio del file. Per
variare la posizione dell'oggetto file si usi
"f.seek(offset, da_cosa)". La posizione viene
calcolata aggiungendo ad offset un punto di riferimento,
selezionato tramite l'argomento da_cosa. Un valore di
da_cosa pari a 0
effettua la misura dall'inizio del file,
1
utilizza come punto di riferimento la posizione attuale,
2
usa la fine del file. da_cosa può essere omesso ed il
suo valore predefinito è pari a 0
, viene quindi usato come
punto di riferimento l'inizio del file.
>>> f=open('/tmp/workfile', 'r+') >>> f.write('0123456789abcdef') >>> f.seek(5) # Va al sesto byte nel file >>> f.read(1) '5' >>> f.seek(-3, 2) # Va al terzo byte prima della fine del file >>> f.read(1) 'd'
Quando si è terminato di lavorare su un file, si chiami
f.close()
per chiuderlo e liberare tutte le risorse di sistema
occupate dal file aperto. Dopo aver invocato f.close()
, i
tentativi di usare l'oggetto file falliranno automaticamente.
>>> f.close() >>> f.read() Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: I/O operation on closed file
Gli oggetti file hanno alcuni metodi addizionali, come isatty() e truncate() che sono usati meno di frequente; si consulti la Libreria di riferimento per una guida completa agli oggetti file.
Le stringhe possono essere scritte e lette da un file con facilità. I
numeri richiedono uno sforzo un po' maggiore, in quanto il metodo
read() restituisce solo stringhe, che dovranno essere passate
a una funzione tipo int(), che prende una stringa
come '123'
e restituisce il corrispondente valore numerico
123. Comunque quando si desidera salvare tipi di dati più complessi,
quali liste, dizionari o istanze di classe, le cose si fanno assai più
complicate.
Per non costringere gli utenti a scrivere e correggere in continuazione codice per salvare tipi di dati complessi, Python fornisce un modulo standard chiamato pickle. Si tratta di un modulo meraviglioso che può prendere pressoché qualsiasi oggetto Python (persino alcune forme di codice Python!) e convertirlo in una rappresentazione sotto forma di stringa; tale processo è chiamato pickling (NdT: letteralmente "conservazione sotto aceto", in pratica si tratta di serializzazione, attenzione a non confonderla con quella del modulo marshal). La ricostruzione dell'oggetto a partire dalla rappresentazione sotto forma di stringa è chiamata unpickling. Tra la serializzazione e la deserializzazione, la stringa che rappresenta l'oggetto può essere immagazzinata in un file, o come dato, o inviata a una macchina remota tramite una connessione di rete.
Se si ha un oggetto x
, e un oggetto file f
aperto in
scrittura, il modo più semplice di fare la serializzazione
dell'oggetto occupa solo una riga di codice:
pickle.dump(x, f)
Per fare la deserializzazione dell'oggetto, se f
è un oggetto
file aperto in scrittura:
x = pickle.load(f)
Ci sono altre varianti del procedimento, usate quando si esegue la serializzazione di molti oggetti o quando non si vuole scrivere i dati ottenuti in un file; si consulti la documentazione completa di pickle nella libreria di riferimento di Python.
pickle è il modo standard per creare oggetti Python che possono essere immagazzinati e riusati da altri programmi o da future esecuzioni dello stesso programma; il termine tecnico è oggetto persistente. Poiché pickle è così ampiamente usato, molti autori di estensioni Python stanno attenti a garantire che i nuovi tipi di dati, quali le matrici, possano essere sottoposti senza problemi a serializzazione ed deserializzazione.
Vedete Circa questo documento... per informazioni su modifiche e suggerimenti.