Dict e file Python

Tabella hash di dict

La struttura di tabella hash chiave/valore efficiente di Python è chiamata "dict". I contenuti di un dizionario possono essere scritti come una serie di coppie chiave:valore tra parentesi graffe { }, ad esempio dict = {key1:value1, key2:value2, ... }. La "dict vuota" è solo una coppia vuota di parentesi graffe {}.

Cercare o impostare un valore in un dict utilizza le parentesi quadre, ad esempio dict['foo'] cerca il valore sotto la chiave "foo". Le stringhe, i numeri e le tuple funzionano come chiavi e qualsiasi tipo può essere un valore. Altri tipi potrebbero o meno funzionare correttamente come chiavi (stringhe e tuple funzionano correttamente perché sono immutabili). La ricerca di un valore non presente nel dizionario genera un KeyError. Utilizza "in" per verificare se la chiave è presente nel dizionario oppure utilizza dict.get(key) che restituisce il valore o None se la chiave non è presente (oppure get(key, not-found) ti consente di specificare il valore da restituire nel caso in cui la chiave non sia presente).

  ## Can build up a dict by starting with the empty dict {}
  ## and storing key/value pairs into the dict like this:
  ## dict[key] = value-for-that-key
  dict = {}
  dict['a'] = 'alpha'
  dict['g'] = 'gamma'
  dict['o'] = 'omega'

  print(dict) ## {'a': 'alpha', 'o': 'omega', 'g': 'gamma'}

  print(dict['a'])     ## Simple lookup, returns 'alpha'
  dict['a'] = 6       ## Put new key/value into dict
  'a' in dict         ## True
  ## print(dict['z'])                  ## Throws KeyError
  if 'z' in dict: print(dict['z'])     ## Avoid KeyError
  print(dict.get('z'))  ## None (instead of KeyError)

detta con i tasti "a" "o" "g"

Per impostazione predefinita, un ciclo for su un dizionario esegue l'iterazione sulle relative chiavi. Le chiavi verranno visualizzate in un ordine arbitrario. I metodi dict.keys() e dict.values() restituiscono in modo esplicito gli elenchi delle chiavi o dei valori. Esiste anche items(), che restituisce un elenco di tuple (chiave, valore), ovvero il modo più efficiente per esaminare tutti i dati chiave/valore nel dizionario. Tutti questi elenchi possono essere passati alla funzione sorted().

  ## By default, iterating over a dict iterates over its keys.
  ## Note that the keys are in a random order.
  for key in dict:
    print(key)
  ## prints a g o

  ## Exactly the same as above
  for key in dict.keys():
    print(key)

  ## Get the .keys() list:
  print(dict.keys())  ## dict_keys(['a', 'o', 'g'])

  ## Likewise, there's a .values() list of values
  print(dict.values())  ## dict_values(['alpha', 'omega', 'gamma'])

  ## Common case -- loop over the keys in sorted order,
  ## accessing each key/value
  for key in sorted(dict.keys()):
    print(key, dict[key])

  ## .items() is the dict expressed as (key, value) tuples
  print(dict.items())  ##  dict_items([('a', 'alpha'), ('o', 'omega'), ('g', 'gamma')])

  ## This loop syntax accesses the whole dict by looping
  ## over the .items() tuple list, accessing one (key, value)
  ## pair on each iteration.
  for k, v in dict.items(): print(k, '>', v)
  ## a > alpha    o > omega     g > gamma

Nota sulla strategia: dal punto di vista del rendimento, il dizionario è uno dei tuoi strumenti più importanti e dovresti utilizzarlo, se possibile, come un modo semplice per organizzare i dati. Ad esempio, potresti leggere un file di log in cui ogni riga inizia con un indirizzo IP e memorizzare i dati in un dizionario utilizzando l'indirizzo IP come chiave e l'elenco delle righe in cui appare come valore. Dopo aver letto l'intero file, puoi cercare qualsiasi indirizzo IP e visualizzare immediatamente l'elenco delle righe. Il dizionario acquisisce dati sparsi e li trasforma in qualcosa di coerente.

Formattazione del dizionario

L'operatore % è utile per sostituire i valori di un dizionario in una stringa in base al nome:

  h = {}
  h['word'] = 'garfield'
  h['count'] = 42
  s = 'I want %(count)d copies of %(word)s' % h  # %d for int, %s for string
  # 'I want 42 copies of garfield'

  # You can also use str.format().
  s = 'I want {count:d} copies of {word}'.format(h)

Canc

L'operatore "del" esegue le eliminazioni. Nel caso più semplice, può rimuovere la definizione di una variabile, come se non fosse stata definita. Del può essere utilizzato anche su elementi o sezioni di elenchi per eliminare quella parte dell'elenco ed eliminare le voci da un dizionario.

  var = 6
  del var  # var no more!

  list = ['a', 'b', 'c', 'd']
  del list[0]     ## Delete first element
  del list[-2:]   ## Delete last two elements
  print(list)      ## ['b']

  dict = {'a':1, 'b':2, 'c':3}
  del dict['b']   ## Delete 'b' entry
  print(dict)      ## {'a':1, 'c':3}

File

La funzione open() apre e restituisce un handle file che può essere utilizzato per leggere o scrivere un file nel solito modo. Il codice f = open('name', 'r') apre il file nella variabile f, pronto per le operazioni di lettura, e utilizza f.close() al termine. Anziché "r", usa "w" per scrivere e "a" per l'aggiunta. Il ciclo for standard funziona per i file di testo, iterando tra le righe del file (funziona solo per i file di testo, non per i file binari). La tecnica del ciclo for è un modo semplice ed efficiente per esaminare tutte le righe di un file di testo:

  # Echo the contents of a text file
  f = open('foo.txt', 'rt', encoding='utf-8')
  for line in f:   ## iterates over the lines of the file
    print(line, end='')    ## end='' so print does not add an end-of-line char
                           ## since 'line' already includes the end-of-line.
  f.close()

La lettura di una riga alla volta ha il vantaggio che non tutto il file deve essere contenuto nella memoria contemporaneamente, il che è utile se vuoi esaminare ogni riga di un file di 10 gigabyte senza utilizzare 10 gigabyte di memoria. Il metodo f.readlines() legge l'intero file in memoria e restituisce i relativi contenuti sotto forma di elenco di righe. Il metodo f.read() legge l'intero file in un'unica stringa, il che può essere un modo pratico per gestire il testo tutto in una volta, come nel caso delle espressioni regolari che vedremo più avanti.

Per la scrittura, il metodo f.write(stringa) è il modo più semplice per scrivere dati in un file di output aperto. In alternativa, puoi utilizzare "print" con un file aperto, ad esempio "print(stringa, file=f)".

File Unicode

Per leggere e scrivere file con codifica Unicode, utilizza una modalità "t" e specifica esplicitamente una codifica:


with open('foo.txt', 'rt', encoding='utf-8') as f:
  for line in f:
    # here line is a *unicode* string

with open('write_test', encoding='utf-8', mode='wt') as f:
    f.write('\u20ACunicode\u20AC\n') #  €unicode€
    # AKA print('\u20ACunicode\u20AC', file=f)  ## which auto-adds end='\n'

Eseguire lo sviluppo incrementale

Quando crei un programma Python, non scriverlo tutto in un solo passaggio. Identifica invece solo un primo traguardo, ad esempio "il primo passaggio è estrarre l'elenco di parole". Scrivi il codice per raggiungere questo traguardo e stampa le strutture di dati a quel punto, quindi puoi eseguire sys.exit(0) in modo che il programma non esegua le parti non completate. Una volta che il codice del traguardo funziona, puoi lavorare al codice per il traguardo successivo. La possibilità di esaminare la stampa delle variabili in un determinato stato può aiutarti a capire come trasformarle per passare allo stato successivo. Python è molto veloce con questo pattern, il che ti consente di apportare una piccola modifica ed eseguire il programma per vedere come funziona. Sfrutta questo rapido turnaround per creare il tuo programma in piccoli passaggi.

Esercizio: wordcount.py

Combinando tutto il materiale di base di Python (stringhe, liste, dizionari, tuple, file), prova l'esercizio di riepilogo wordcount.py negli Esercizi di base.