Dict e file Python

Tabella hash detta

La struttura efficiente della tabella hash di chiave/valore di Python è chiamata "dict". Il contenuto di un dict può essere scritto come una serie di coppie chiave:valore all'interno di parentesi graffe { }, ad esempio dict = {key1:value1, chiave2:value2, ... }. Il "dict vuoto" è solo una coppia vuota di parentesi graffe {}.

La ricerca o l'impostazione di un valore in una tabella utilizza le parentesi quadre. Ad esempio, dict['foo'] cerca il valore sotto la chiave "foo". Stringhe, numeri e 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 poiché sono immutabili). La ricerca di un valore che non è presente nel dict genera un errore KeyError: usa "in" per controllare se la chiave è nel dict oppure usa dict.get(key) che restituisce il valore o None se la chiave non è presente (oppure get(key, not-found) ti consente di specificare quale valore restituire in caso di non trovato).

  ## 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)

dettatura con i tasti "a" "o" "g"

Un ciclo for su un dizionario esegue l'iterazione delle sue chiavi per impostazione predefinita. Le chiavi vengono visualizzate in ordine arbitrario. I metodi dict.keys() e dict.values() restituiscono esplicitamente elenchi di chiavi o valori. C'è anche una funzione items() che restituisce un elenco di tuple (chiave, valore), il che è il modo più efficiente per esaminare tutti i dati dei valori-chiave nel dizionario. Tutti questi elenchi possono essere passati alla funzione order().

  ## 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 delle prestazioni, il dizionario è uno dei migliori strumenti e dovreste utilizzarlo come metodo semplice per organizzare i dati. Ad esempio, potresti leggere un file di log in cui ogni riga inizia con un indirizzo IP e archiviare i dati in una dettatura utilizzando l'indirizzo IP come chiave e l'elenco di righe in cui compare come valore. Dopo aver letto l'intero file, puoi cercare qualsiasi indirizzo IP e visualizzare immediatamente l'elenco di righe. Il dizionario prende i dati sparsi e li trasforma in qualcosa di coerente.

Formattazione dei dettati

L'operatore % consente di sostituire facilmente i valori di una dettatura 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)

Del

L'operatore "del" esegue le eliminazioni. Nel caso più semplice, può rimuovere la definizione di una variabile, come se questa non fosse stata definita. La funzionalità Canc può essere utilizzata anche sugli elementi o sulle sezioni dell'elenco per eliminare quella parte dell'elenco e 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}

Files

La funzione open() apre e restituisce un handle di file che può essere utilizzato per leggere o scrivere un file come di consueto. Il codice f = open('name', 'r') apre il file nella variabile f, pronto per le operazioni di lettura, e al termine usa f.close(). Anziché "r", utilizza "w" per scrivere e "a" per aggiungere. Lo standard for-loop funziona per i file di testo, eseguendo l'iterazione sulle righe del file (funziona solo per i file di testo, non per i file binari). La tecnica for-loop è un modo semplice ed efficiente per esaminare tutte le righe in 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 la buona qualità che non tutto il file deve essere in memoria contemporaneamente: è utile se vuoi esaminare ogni riga di un file da 10 gigabyte senza utilizzare 10 gigabyte di memoria. Il metodo f.readlines() legge l'intero file in memoria e restituisce i 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 trattare tutto il testo contemporaneamente, come con le espressioni regolari che vedremo più avanti.

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

File Unicode

Per leggere e scrivere file codificati Unicode, utilizza una modalità "t" e specifica in modo esplicito 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'

Esercitare lo sviluppo incrementale

Creare un programma Python, non scrivere tutto in un solo passaggio. Identifica invece solo un primo traguardo, ad esempio "beh, il primo passaggio è estrarre l'elenco di parole". Scrivi il codice per raggiungere questo traguardo e solo a quel punto stampare le strutture di dati, quindi puoi eseguire una sys.exit(0) in modo che il programma non vada avanti nelle sue parti non completate. Una volta che il traguardo sarà valido, potrai lavorare al codice per il traguardo successivo. Riuscire a visualizzare la stampa delle variabili in uno stato può aiutarti a pensare a come devi trasformarle per passare allo stato successivo. Python è molto veloce con questo pattern, consentendo di apportare una piccola modifica ed eseguire il programma per vedere come funziona. Approfitta di questa rapidità per creare il tuo programma in pochi passaggi.

Allenamento: wordcount.py

Combinando tutto il materiale di base Python (stringhe, elenchi, dettati, tuple, file), prova l'esercizio di riepilogo wordcount.py in Esercizi di base.