Formati dati 1
Scarica zip esercizi
In questi tutorial parleremo di formati dei dati:
File testuali
File a linee
CSV (dati tabulari)
JSON (dati ad albero, menzione)
File binari:
fogli Excel (menzione)
Faremo anche una breve panoramica sui cataloghi open data e menzioneremo qualche licenza (Creative Commons)
Che fare
scompatta lo zip in una cartella, dovresti ottenere qualcosa del genere:
formats
formats1-lines.ipynb
formats1-lines-sol.ipynb
formats2-csv.ipynb
formats2-csv-sol.ipynb
formats3-json.ipynb
formats3-json-sol.ipynb
formats4-chal.ipynb
jupman.py
ATTENZIONE: Per essere visualizzato correttamente, il file del notebook DEVE essere nella cartella szippata.
apri il Jupyter Notebook da quella cartella. Due cose dovrebbero aprirsi, prima una console e poi un browser. Il browser dovrebbe mostrare una lista di file: naviga la lista e apri il notebook
formats1-lines.ipynb
Prosegui leggendo il file degli esercizi, ogni tanto al suo interno troverai delle scritte ESERCIZIO, che ti chiederanno di scrivere dei comandi Python nelle celle successive.
Scorciatoie da tastiera:
Per eseguire il codice Python dentro una cella di Jupyter, premi
Control+Invio
Per eseguire il codice Python dentro una cella di Jupyter E selezionare la cella seguente, premi
Shift+Invio
Per eseguire il codice Python dentro una cella di Jupyter E creare una nuova cella subito dopo, premi
Alt+Invio
Se per caso il Notebook sembra inchiodato, prova a selezionare
Kernel -> Restart
File a linee
I file a linee tipicamente sono file di testo che contengono informazioni raggruppate per linee. Un esempio usando personaggi storici potrebbe essere un file così:
Leonardo
da Vinci
Sandro
Botticelli
Niccolò
Macchiavelli
Si nota subito una regolarità: le prime due linee contengono i dati di Leonardo da Vinci, prima il nome e poi il cognome. Le successive due linee hanno invece i dati di Sandro Botticelli, di nuovo prima il nome e poi il cognome, e così via
Un programma che potremo voler fare potrebbe essere leggere le linee e stampare a video nomi e cognomi così:
Leonardo da Vinci
Sandro Botticelli
Niccolò Macchiavelli
Per iniziare ad avere un’approssimazione del risultato finale, possiamo aprire il file, leggere solo la prima linea e stamparla:
[1]:
with open('people-simple.txt', encoding='utf-8') as f:
linea=f.readline()
print(linea)
Leonardo
Che è successo? Esaminiamo le varie linee:
il comando open
Il comando
open('people-simple.txt', encoding='utf-8')
ci permette di aprire il file di testo dicendo a Python il percorso del file 'people-simple.txt'
e la codifica con cui è stato scritto (encoding='utf-8'
).
La codifica
La codifica dipende dal sistema operativo e dell’editor con cui è stato scritto il file. Quando apriamo un file, Python non può divinare la codifica, e se non gliela specifichiamo potrebbe aprirlo assumendo una codifica diversa dall’originale - tradotto, affidandoci al caso o sbagliando codifica in seguito potremmo vedere dei caratteri strani (tipo quadratini invece di lettere accentate).
In genere, quando apri un file, prova prima a specificare la codifica utf-8
che è la più comune scrivendo encoding='utf-8'
, e se per caso non va bene prova invece encoding='latin-1'
(solitamente utile se il file è stato scritto su sistemi Windows). Se apri file scritti in posti più esotici, tipo in Cina, potresti dover usare un’altro encoding. Per approfondire queste questioni, vedere capitolo Stringhe - encodings e
relativi riferimenti.
il blocco with
Il with
definisce un blocco con all’interno le istruzioni:
with open('people-simple.txt', encoding='utf-8') as f:
linea=f.readline()
print(linea)
Abbiamo usato il with
per dire a Python che in ogni caso, anche se accadono errori, vogliamo che dopo aver usato il file, e cioè eseguito le istruzioni nel blocco interno (il linea=f.readline()
e print(linea)
) Python deve chiudere automaticamente il file. Chiudere propriamente un file evita di sprecare risorse di memoria e creare errori paranormali. Se vuoi evitare di andare a caccia di file zombie mai chiusi, ricordati sempre di aprire i file nei blocchi with
! Inoltre, alla fine
della riga nella parte as f:
abbiamo assegnato il file ad una variabile chiamata qui f
, ma potevamo usare un qualunque altro nome.
ATTENZIONE: Per indentare il codice, usa SEMPRE sequenze di 4 spazi bianchi. Sequenze di 2 soli spazi per quanto consentite non sono raccomandate.
ATTENZIONE: A seconda dell’editor che usi, premendo TAB potresti ottenere una sequenza di spazi bianchi come accade in Jupyter (4 spazi che sono raccomandati), oppure un carattere speciale di tabulazione (da evitare)! Per quanto noiosa questa distinzione ti possa apparire, ricordatela perchè potrebbe generare errori molto difficili da scoprire.
ATTENZIONE: Nei comandi che creano blocchi come il with
, ricordati di mettere sempre il carattere dei doppi punti :
alla fine della linea !
Il comando
linea=f.readline()
mette nella variabile linea
l’intera linea, come una stringa. Attenzione: la stringa conterrà alla fine anche il carattere speciale di ritorno a capo !
Ti chiederai da dove venga fuori quel readline
. Come quasi tutto in Python, la nostra variabile f
che rappresenta il file appena aperto è un oggetto, e ogni oggetto, a seconda del suo tipo, ha dei metodi particolari che possiamo usare su di esso. In questo caso il metodo è readline
.
Il comando seguente stampa il contenuto della stringa:
print(linea)
Esercizio - prima lettura
✪ Prova a riscrivere nella cella qua il blocco with appena visto, ed esegui la cella premendo Control-Invio. Riscrivi il codice con le dita, non con il copia e incolla ! Fai attenzione ad indentare correttamente con gli spazi il blocco.
Mostra soluzione[2]:
# scrivi qui
Esercizio - ambientiamoci
✪ immagino ti starai chiedendo che cosa è esattamente quella f
, e cosa faccia esattamente il metodo readline
. Quando ti trovi in queste situazioni, puoi aiutarti con le funzioni type
e help
. Questa volta, copia e incolla direttamente sempre lo stesso codice qua sotto, ma aggiungi a mano dentro il blocco with
i comandi:
print(type(f))
help(f.readline) # Attenzione: ricordati il 'f.' prima del readline !!
help(f)
Ogni volta che aggiungi qualcosa, prova ad eseguire con Control+Invio e vedere cosa succede.
Mostra soluzione[3]:
# scrivi qui il codice (copia e incolla)
Leonardo
type(f): <class '_io.TextIOWrapper'>
Help on built-in function readline:
readline(size=-1, /) method of _io.TextIOWrapper instance
Read until newline or EOF.
Returns an empty string if EOF is hit immediately.
Prima abbiamo messo il contenuto della prima linea nella variabile line
, ora potremmo metterlo in una variabile dal nome più significativo, come nome
. Non solo, possiamo anche direttamente leggere la linea successiva nella variabile cognome
e poi stampare la concatenazione delle due:
[4]:
with open('people-simple.txt', encoding='utf-8') as f:
nome=f.readline()
cognome=f.readline()
print(nome + ' ' + cognome)
Leonardo
da Vinci
PROBLEMA ! La stampa mette comunque uno strano ritorno a capo. Come mai? Se ti ricordi, prima ho detto che readline
legge il contenuto della linea in una stringa aggiungendo alla fine anche il carattere speciale di ritorno a capo. Per eliminarlo, puoi usare il comando rstrip()
:
[5]:
with open('people-simple.txt', encoding='utf-8') as f:
nome=f.readline().rstrip()
cognome=f.readline().rstrip()
print(nome + ' ' + cognome)
Leonardo da Vinci
✪ 1.3 ESERCIZIO: Di nuovo, riscrivi il blocco qua sopra nella cella sotto, ed esegui la cella con Control+Invio. Domanda: che succede se usi strip()
invece di rstrip()
? Ed lstrip()
? Riesci a dedurre il significato di r
e l
? Se non ci riesci, prova ad usare il comando python help
chiamando help(string.rstrip)
[6]:
# scrivi qui
Leonardo da Vinci
Benissimo, abbiamo la prima linea ! Adesso possiamo leggere tutte le linee in sequenza. A tal fine possiamo usare un ciclo while
:
[7]:
with open('people-simple.txt', encoding='utf-8') as f:
linea=f.readline()
while linea != "":
nome = linea.rstrip()
cognome=f.readline().rstrip()
print(nome + ' ' + cognome)
linea=f.readline()
Leonardo da Vinci
Sandro Botticelli
Niccolò Macchiavelli
NOTA: In Python ci sono metodi più concisi per leggere un file di testo linea per linea che vedremo in seguito, intanto abbiamo questo approccio per esplicitare tutti i passaggi.
Cosa abbiamo fatto? Per prima cosa, abbiamo aggiunto un ciclo while
in un nuovo blocco
ATTENZIONE: nel nuovo blocco while, dato che è già all’interno del blocco esterno with
, le istruzioni sono indentate di 8 spazi e non più 4! Se per caso sbagli gli spazi, possono succedere brutti guai!
Prima leggiamo una linea, e due casi sono possibili:
siamo alla fine del file (o il file è vuoto): in questo caso la chiamata a
readline()
ritorna una stringa vuotanon siamo alla fine del file: la prima linea è messa come una stringa dentro la variabile
linea
. Dato che Python internamente usa un puntatore per tenere traccia della posizione a cui si è durante la lettura del file, dopo una lettura questo puntatore è mosso all’inizio della riga successiva. In questo modo una chiamata successiva areadline()
leggerà la linea dalla nuova posizione.
Nel blocco while
diciamo a Python di continuare il ciclo fintanto che linea
non è vuota. In questo caso, dentro il blocco while
estraiamo il nome dalla linea e lo mettiamo nella variabile nome
(rimuovendo il carattere extra di ritorno a capo con la rstrip()
come fatto in precedenza), e poi procediamo leggendo la nuova riga ed estraendo il risultato dentro la variabile cognome
. Infine, leggiamo di nuovo la linea dentro la variabile linea
così sarà pronta per la
prossima iterazione di estrazione nome. Se la linea
è vuota il ciclo terminerà:
while linea != "": # entra il ciclo se la linea contiene caratteri
nome = linea.rstrip() # estrae il nome
cognome=f.readline().rstrip() # legge la nuova linea ed estrae il cognome
print(nome + ' ' + cognome)
linea=f.readline() # legge la prossima linea
Esercizio - riscrivi
✪ Di nuovo come prima, riscrivi nella cella qua sotto il codice col while appena spiegato, facendo MOLTA attenzione all’indentazione (per la linea del with esterno fai pure copia e incolla):
Mostra soluzione[8]:
# scrivi qui il codice col while interno
Esercizio - stampa people-complex
Guarda il file people-complex.txt
, più complesso:
nome: Leonardo
cognome: da Vinci
data di nascita: 1452-04-15
nome: Sandro
cognome: Botticelli
data di nascita: 1445-03-01
nome: Niccolò
cognome: Macchiavelli
data di nascita: 1469-05-03
Supponendo di leggere il file per voler stampare questo output, come faresti ?
Leonardo da Vinci, 1452-04-15
Sandro Botticelli, 1445-03-01
Niccolò Macchiavelli, 1469-05-03
Suggerimento 1: Per ottenere dalla stringa 'abcde'
la sottostringa 'cde'
, che inizia all’indice 2, puoi usare l’operatore di parentesi quadre, indicando l’indice di inizio seguito dai doppi punti :
[9]:
x = 'abcde'
x[2:]
[9]:
'cde'
[10]:
x[3:]
[10]:
'de'
Suggerimento 2: Per sapere la lunghezza di una stringa, usa la funzione len
:
[11]:
len('abcde')
[11]:
5
✪ 1.5 ESERCIZIO: Scrivi qua sotto la soluzione dell’esercizio ‘People complex’:
Mostra soluzione[12]:
# scrivi qui
Leonardo da Vinci, 1452-04-15
Sandro Botticelli, 1445-03-01
Niccolò Macchiavelli, 1469-05-03
Esercizio - tabella people-complex
✪✪ Spesso vorremo mettere quanto letto in una tabella, prova adesso a scrivere del codice che ne costruisce una come lista di liste. Dopo l’esecuzione del tuo codice dovrebbe risultare:
>>> from pprint import pprint
>>> pprint(tabella)
[['Leonardo', 'da Vinci', '1452-04-15'],
['Sandro', 'Botticelli', '1445-03-01'],
['Niccolò', 'Macchiavelli', '1469-05-03']]
SUGGERIMENTO: Comincia creando una lista vuota e poi aggiungendo elementi con il metodo .append
[13]:
from pprint import pprint
# scrivi qui
[['Leonardo', 'da Vinci', '1452-04-15'],
['Sandro', 'Botticelli', '1445-03-01'],
['Niccolò', 'Macchiavelli', '1469-05-03']]
Leggere con un for
Dopo aver esplicitato per bene i passaggi di una lettura con il ciclo while
, vediamo adesso un sistema più comodo (ma un po’ più ‘magico’) per leggere un file di testo linea per linea usando un semplice ciclo for
:
[14]:
with open('people-simple.txt', encoding='utf-8') as f:
for linea in f:
print(linea)
Leonardo
da Vinci
Sandro
Botticelli
Niccolò
Macchiavelli
Se guardi bene, noterai che non abbiamo più chiamate a f.readline()
Quando incontra il ciclo, Python riconosce che f
è un file di testo, e suppone che la cosa che ci interessa di più coi file di testo sia leggere linee: interpreta perciò la variabile f
come una sequenza di linee, e ad ogni iterazione assegna alla variabile linea
(ma potrebbe essere un qualunque nome a nostro piacimento) i caratteri letti fino al primo ritorno a capo che trova (incluso).
Nota che questo comportamento speciale avviene solo perchè stiamo leggendo file di testo, nel caso di file d’altro tipo (es. file binari) verrebbero letti valori di tipo completamente diverso.
Adesso che abbiamo trovato questa comoda alternativa, possiamo chiederci quando dovremmo usare il while
e quando il for
:
il
for
tipicamente viene usato quando dobbiamo iterare tutto il fileil
while
conviene quando vogliamo maggior controllo sul processo di lettura, per esempio, se stiamo cercando qualcosa in un file enorme, sarà certamente più efficente fermarsi appena lo troviamo: con unwhile
possiamo interrompere il ciclo sfruttando la condizione booleana di controllo già prevista dal costrutto, invece con ilfor
saremmo costretti ad usare comandibreak
e/ocontinue
che sono poco eleganti e portano facilmente a introdurre errori di programmazione indesiderati. Per degli esempi di ricerca vedere il foglio Cicli while - ricercare in una sequenza (sono ricerche su liste invece che file, ma il concetto è lo stesso).
Cos’è esattamente f
?
Abbiamo detto che f
viene interpretato come una sequenza di righe, ed è iterabile. Durante il ciclo for
ad ogni iterazione gli chiediamo di leggere una nuova linea, che viene messa nella variabile linea
. Quindi possiamo chiederci: cosa succede se stampiamo direttamente f
, senza usare nessun for
? Vedremo una bella lista o qualcos’altro? Proviamo:
[15]:
with open('people-simple.txt', encoding='utf-8', newline='') as f:
print(f)
<_io.TextIOWrapper name='people-simple.txt' mode='r' encoding='utf-8'>
Quello che vediamo è piuttosto deludente.
Esercizio - da file a lista
✪ Se hai visto il foglio sulle sequenze, a un certo punto ci siamo trovati nella stessa situazione, quando abbiamo provato a stampare un range. Che potremmo fare per risolvere la situazione? Prova a mettere tutte le linee in una lista
USA una sola linea di codice
per adesso non preoccuparti dei
\n
finali
Eseguendo il tuo codice, dovresti vedere:
['Leonardo\n', 'da Vinci\n', 'Sandro\n', 'Botticelli\n', 'Niccolò \n', 'Macchiavelli']
[16]:
with open('people-simple.txt', encoding='utf-8', newline='') as f:
# scrivi qui
Esercizio - ripuliamo
✪ Adesso prova anche a togliere i ritorni a capo
USA una list comprehension in una sola linea di codice
Eseguendo il tuo codice, dovresti vedere:
['Leonardo', 'da Vinci', 'Sandro', 'Botticelli', 'Niccolò ', 'Macchiavelli']
[17]:
with open('people-simple.txt', encoding='utf-8', newline='') as f:
# scrivi qui
Consumare un file
Non tutte le sequenze sono uguali. Da quello che hai visto finora, in Python scorrere un file con un for
assomiglia molto a scorrere una lista. Che è molto comodo, ma bisogna stare attenti ad alcune cose.
A volte i file potrebbero occupare terabyte, forzandoci in questi casi a scorrere il file un po’ alla volta invece di caricare tutto in memoria.
Ma cosa succede se proviamo a scorrere un file due volte all’interno della stessa with
? E se proviamo ad usarlo fuori dal with
, che succede? Guarda i prossimi esercizi per scoprirlo.
Esercizio - due print
✪ Prendendo la soluzione all’esercizio di prima, prova a chiamare print(list(f))
due volte, in sequenza. Ottieni la stessa stampa entrambe le volte?
[18]:
# scrivi qui
Esercizio - tutto a sinistra
✪ Prendendo la soluzione all’esercizio di prima (usando una sola print
), prova qua sotto a spostare la print
tutta a sinistra (eliminando gli spazi). Funziona ancora?
[19]:
# scrivi qui
✪✪✪ ESERCIZIO 2.9: Adesso che abbiamo capito un po’ che tipo di bestia è f
, prova a leggere il file people-complex.txt e riprodurre questo risultato simile a quanto già fatto in precedenza, ma questa volta usa un ciclo for
in.
Aggiungi anche una intestazione e metti il risultato in una variabile
tab2
Dopo l’esecuzione del tuo codice, deve risultare:
>>> from pprint import pprint
>>> pprint(tab2)
[['Nome', 'Cognome', 'Data di nascita'],
['Leonardo', 'da Vinci', '1452-04-15'],
['Sandro', 'Botticelli', '1445-03-01'],
['Niccolò ', 'Macchiavelli', '1469-05-03']]
[20]:
with open('people-complex.txt', encoding='utf-8', newline='') as f:
# scrivi qui
[['Nome', 'Cognome', 'Data di nascita'],
['Leonardo', 'da Vinci', '1452-04-15'],
['Sandro', 'Botticelli', '1445-03-01'],
['Niccolò ', 'Macchiavelli', '1469-05-03']]
Altri esercizi
Esercizio - MattoneMatto
✪✪✪ La compagnia di costruzioni MattoneMatto è interessata all’acquisto a prezzi di svendita di un lotto di appartmenti da ristrutturare: non fidandosi delle dichiarazioni dei proprietari, manda un suo ispettore a fare una rilevazione d’accertamento. Per ogni edificio, l’ispettore ha scritto rapidamente sul blocco note dei campi come il codice civico, la superficie, l’indice di efficenza energetico EPI e possibilmente altri.
Scrivi del codice che dato il nome di un file di un quartiere, mette nella variabile edifici
una lista di dizionari con i campi per ciascun edificio. Puoi assumere che i nomi dei campi e i valori non possano mai contenere caratteri di blank (spazi, tab, ritorni a capo…).
ATTENZIONE: i file sono scritti a mano e tra i campi vi possono essere un numero di blank arbitrario (spazi, tab, etc), per gestirli al meglio rileggiti bene i dettagli del metodo split()
Per esempio, il file quartiere1.txt si presenta così:
civico=3 superficie=60 EPI=C
civico=2 superficie=70 EPI=G giardino=80
civico=4 superficie=90 EPI=B terrazzi=14 posti_auto=2
civico=1 superficie=100 EPI=A2 terrazzi=20
Dato:
nome_file = 'quartiere1.txt'
dopo il tuo codice, deve risultare:
>>> from pprint import pprint
>>> pprint(edifici, width=150)
[{'EPI': 'C', 'civico': '3', 'superficie': '60'},
{'EPI': 'G', 'civico': '2', 'giardino': '80', 'superficie': '70'},
{'EPI': 'B', 'civico': '4', 'posti_auto': '2', 'superficie': '90', 'terrazzi': '14'},
{'EPI': 'A2', 'civico': '1', 'superficie': '100', 'terrazzi': '20'}]
USA un
for
per leggere il fileIMPOSTA l’encoding come
utf-8
NON ASSUMERE che i campi abbiano sempre lo stesso nome nè che siano in particolare ordine (guarda anche quartiere2.txt)
[22]:
nome_file = 'quartiere1.txt'
nome_file = 'quartiere2.txt' # [ {'civ': '5', 'epi': 'B', 'sup': '20'},
# {'civ': '9', 'epi': 'D', 'interno': 'c', 'sup': '10'} ]
# scrivi qui
Esercizio immersione-in-python-toc
Questo esercizio è più difficile, se sei alle prime armi puoi saltarlo e passare ai CSV.
Il libro Immersione in Python in Italiano è bello e ti fornisce un PDF, che però ha un problema: se provi a stamparlo scoprirai che manca l’indice. Senza perderci d’animo, abbiamo trovato un programmino che ci ha estratto i titoli in un file come segue, che però come scoprirai non è esattamente bello da vedere. Dato che siamo Python ninja, abbiamo deciso di trasformare i titoli grezzi in una tabella dei contenuti vera e propria. Sicuramente ci sono metodi più furbi per compiere questa operazione, come caricare il pdf in Python con una apposita libreria per i pdf, ma pareva un esercizio interessante.
Ti viene consegnato il file immersione-in-python-toc.txt:
BookmarkBegin
BookmarkTitle: Il vostro primo programma Python
BookmarkLevel: 1
BookmarkPageNumber: 38
BookmarkBegin
BookmarkTitle: Immersione!
BookmarkLevel: 2
BookmarkPageNumber: 38
BookmarkBegin
BookmarkTitle: Dichiarare funzioni
BookmarkLevel: 2
BookmarkPageNumber: 41
BookmarkBeginint
BookmarkTitle: Argomenti opzionali e con nome
BookmarkLevel: 3
BookmarkPageNumber: 42
BookmarkBegin
BookmarkTitle: Scrivere codice leggibile
BookmarkLevel: 2
BookmarkPageNumber: 44
BookmarkBegin
BookmarkTitle: Stringhe di documentazione
BookmarkLevel: 3
BookmarkPageNumber: 44
BookmarkBegin
BookmarkTitle: Il percorso di ricerca di import
BookmarkLevel: 2
BookmarkPageNumber: 46
BookmarkBegin
BookmarkTitle: Ogni cosa è un oggetto
BookmarkLevel: 2
BookmarkPageNumber: 47
Scrivi un programma python per stampare e video il seguente output:
Il vostro primo programma Python 38
Immersione! 38
Dichiarare funzioni 41
Argomenti opzionali e con nome 42
Scrivere codice leggibile 44
Stringhe di documentazione 44
Il percorso di ricerca di import 46
Ogni cosa è un oggetto 47
Per questo esercizio, dovrai inserire nell’output degli spazi artificiali, in una quantità determinata dalle righe BookmarkLevel
.
DOMANDA: che cos’è lo strano valore è
alla fine del file originale ? Dobbiamo riportarlo nell’output ?
SUGGERIMENTO 1: Per convertire una stringa in numero intero, usa la funzione int
:
[23]:
x = '5'
[24]:
x
[24]:
'5'
[25]:
int(x)
[25]:
5
Attenzione: int(x)
ritorna un valore, e non modifica mai l’argomento x
!
SUGGERIMENTO 2: Per sostituire un sottostringa in una stringa, si può usare la funzione replace:
[26]:
x = 'abcde'
x.replace('cd', 'HELLO' )
[26]:
'abHELLOe'
SUGGERIMENTO 4: Finchè c’è una sola sequenza da sostituire, va bene il replace, ma se avessimo un milione di sequenze orribili come >
, >
, &x3e;
, che faremmo? Da bravi data cleaner, possiamo riconoscere che sono sequenze di escape HTML, perciò potremmo usare dei metodi specifici per queste sequenze come html.unescape. Provalo invece del replace
e guarda se funziona!
NOTA: Prima di usare il metodo html.unescape
, importa il modulo html
con il comando:
import html
SUGGERIMENTO 3: Per scrivere n copie di un carattere, usa *
come qua:
[27]:
"b" * 3
[27]:
'bbb'
[28]:
"b" * 7
[28]:
'bbbbbbb'
✪✪✪ 1.6 ESERCIZIO: Scrivi qua sotto la soluzione per file a linee immersione-in-python-toc, e prova ad eseguirla premendo Control + Invio:
Mostra soluzione[29]:
# scrivi qui
Il vostro primo programma Python 38
Immersione! 38
Dichiarare funzioni 41
Argomenti opzionali e con nome 42
Scrivere codice leggibile 44
Stringhe di documentazione 44
Il percorso di ricerca di import 46
Ogni cosa è un oggetto 47
Prosegui
Continua con i file tabellari CSV