Dict y archivo de Python

Tabla de hash de Dict

La estructura eficiente de la tabla hash de clave-valor de Python se denomina "dict". El contenido de un dict se puede escribir como una serie de pares clave-valor entre llaves { }, por ejemplo, dict = {key1:value1, key2:value2, ... }. El "empty dict" es solo un par vacío de llaves {}.

La búsqueda o configuración de un valor en un diccionario usa corchetes; p.ej., dict['foo'] busca el valor debajo de la clave 'foo'. Las cadenas, los números y las tuplas funcionan como claves, y cualquier tipo puede ser un valor. Otros tipos pueden o no funcionar correctamente como claves (las strings y tuplas funcionan correctamente, ya que son inmutables). La búsqueda de un valor que no está en el diccionario arroja un KeyError. Usa "in" para verificar si la clave está en el diccionario, o usa dict.get(key), que muestra el valor, o None si la clave no está presente (o get(key, not-found) te permite especificar qué valor mostrar en el caso de no encontrado).

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

dict con claves 'a' 'o' 'g'

Un bucle for en un diccionario itera en sus claves de forma predeterminada. Las claves aparecerán en un orden arbitrario. Los métodos dict.keys() y dict.values() devuelven listas de claves o valores de forma explícita. También hay un elemento items() que devuelve una lista de tuplas (clave, valor), que es la manera más eficaz de examinar todos los datos de pares clave-valor en el diccionario. Todas estas listas pueden pasarse a la función ordenada().

  ## 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 sobre la estrategia: desde el punto de vista del rendimiento, el diccionario es una de sus mejores herramientas, y debería usarlo siempre que sea posible como una forma fácil de organizar los datos. Por ejemplo, puedes leer un archivo de registro donde cada línea comienza con una dirección IP y almacenar los datos en un dict usando la dirección IP como clave y la lista de líneas donde aparece como valor. Una vez que hayas leído el archivo completo, podrás buscar cualquier dirección IP y ver al instante su lista de líneas. El diccionario toma datos dispersos y los convierte en algo coherente.

Formato de Dict

El operador % funciona de manera conveniente para sustituir los valores de un diccionario en una string por nombre:

  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

El operador "del" realiza eliminaciones. En el caso más simple, se puede quitar la definición de una variable, como si esa variable no se hubiera definido. Del también se puede usar en fragmentos o elementos de lista para borrar esa parte de la lista y borrar entradas de un diccionario.

  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 función open() se abre y muestra un controlador de archivo que se puede usar para leer o escribir un archivo de la manera habitual. El código f = open('name', 'r') abre el archivo en la variable f, listo para las operaciones de lectura, y usa f.close() cuando finaliza. En lugar de “r”, usa “w” para escribir y “a” para anexar. El bucle for estándar funciona con archivos de texto, iterando a través de las líneas del archivo (esto solo funciona para archivos de texto, no binarios). La técnica de bucle for es una manera simple y eficiente de ver todas las líneas en un archivo de texto:

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

Leer una línea a la vez tiene la buena calidad de que no todos los archivos necesitan caber en la memoria al mismo tiempo. Es práctico si quieres ver cada línea de un archivo de 10 gigabytes sin usar 10 gigabytes de memoria. El método f.readlines() lee el archivo completo en la memoria y muestra su contenido como una lista de sus líneas. El método f.read() lee el archivo completo en una sola cadena, que puede ser una manera práctica de tratar todo el texto al mismo tiempo, como con las expresiones regulares que veremos más adelante.

Para escribir, el método f.write(string) es la forma más fácil de escribir datos en un archivo de salida abierto. También puedes usar "print" con un archivo abierto, como "print(string, file=f)".

Archivos Unicode

Para leer y escribir archivos codificados en Unicode, usa un modo `'t'` y especifica explícitamente una codificación:


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'

Ejercita el desarrollo incremental

Si compilas un programa de Python, no escribas todo en un solo paso. En cambio, identifica solo un primer hito, p.ej., "bueno, el primer paso es extraer la lista de palabras". Escribe el código para llegar a ese hito y simplemente imprime tus estructuras de datos en ese punto, y luego puedes hacer un sys.exit(0) para que el programa no se ejecute en las partes no completadas. Una vez que el código de hito funcione, puedes trabajar en el código para el siguiente hito. Poder ver la impresión de tus variables en un estado puede ayudarte a pensar en cómo necesitas transformar esas variables para llegar al siguiente estado. Python es muy rápido con este patrón, lo que te permite hacer un pequeño cambio y ejecutar el programa para ver cómo funciona. Aprovecha ese tiempo de respuesta rápido para crear tu programa en pequeños pasos.

Ejercicio: wordcount.py

Si combinas todo el material básico de Python (strings, listas, diccionarios, tuplas y archivos), prueba el ejercicio de resumen wordcount.py en los Ejercicios básicos.