Diccionarios: dict
Los diccionarios en Python son una estructura de datos preparadas para almacenar
colecciones de elementos (separados por coma) compuestos de una clave y un valor
(suele llamarlos en ingles key, value).
Los diccionarios se delimitan con llaves {}
.
Veamos un ejemplo:
persona = {
"nombre": "Luis",
"apellido": "Colon",
"edad": 32
}
type(persona)
# devuelve <class 'dict'>
Los valores pueden accederse directamente desde sus claves. Esto es así tanto para leer como para modificar cada elemento. Las claves son únicas, no puede haber dos elementos con la misma clave.
persona = {
"nombre": "Luis",
"apellido": "Colon",
"edad": 32
}
print(f'Nombre: {persona["nombre"]} {persona["apellido"]} tiene {persona["edad"]} años')
'Luis Colon tiene 32 años'
print(persona["nombre"])
'Luis'
edad = persona["edad"]
print(edad)
32
persona["apellido"] = "Gonzalez"
print(persona)
{"nombre": "Luis", "apellido": "Gonzalez", "edad": 32}
En algunas ocasiones no vamos a tener certeza de que las claves a las que queremos acceder existen.
persona = {
"nombre": "Luis",
"apellido": "Colon",
"edad": 32
}
# La siguiente línea lanzará un error (la clave no existe)
persona["clave_que_no_exite"]
# Para acceder a elementos de los que no sabemos si su clave existe,
# usamos la función "get" de los diccionarios
persona.get("clave_que_no_exite")
# Si la clave (key) no existe la anterior línea no va a lanzar
# un error. Simplemente devolverá None (es el "nada" de Python)
# Si queremos un valor predeterminado para cuando la clave no
# esta definida podemos usar el segundo parámetro opcional de "get"
persona.get("clave_que_no_exite", "valor_predeterminado")
# Tambien es posible "preguntar" si una clave existe
if "clave_buscada" in persona:
print("clave_buscada SI existe como clave en 'persona'")
# Esto es posible porque los diccionarios definen un iterador con la
# lista de sus claves
for key in persona:
print(f"Clave en persona: {key}")
Cada par de clave-valor es denominado como elemento (item).
La función items
de los diccionarios devuleve un objeto iterable
que podemos navegar con for
y que devuelve en cada paso una
clave y un valor.
persona = {
"nombre": "Juan",
"apellido": "Colon",
"edad": 32
}
for k, v in persona.items():
print(f'Item encontrado: Key:{k}, Value: {v}')
# Item encontrado: Key:nombre, Value: Juan
# Item encontrado: Key:apellido, Value: Colon
# Item encontrado: Key:edad, Value: 32
Los valores puede ser de cualquier tipo e incluso conformar estructuras muy complejas.
Ejemplo:
persona = {
"nombre": "Luis",
"apellido": "Colon",
"edad": 32,
"estudios": {
"primario": True,
"secundario": True,
"terciario": False,
"universitario": False
},
"experiencia_laboral": {
"2005-2008": {
"empresa": "Ferreteria el cosito del coso",
"cargo": "Vendedor",
"sueldo": 45000,
"tareas": ["atender publico", "compras"]
},
"2009-2011": {
"empresa": "Escuela Tecnica San Martin",
"cargo": "profesor",
"sueldo": 75000,
"tareas": ["dictar clases", "elaborar cursos"]
}
}
}
En el ejemplo anterior persona["estudios"]
es a su vez un diccionario por lo que
tiene a su ves las propiedades de un nuevo objeto de este tipo.
Las siguientes lineas son válidas para la estructura recién definida.
print(persona["estudios"]["primario"])
True
if persona["estudios"]["secundario"]:
print('La persona termino el secundario')
En el ejemplo anterior persona["experiencia_laboral"]["2005-2008"]["tareas"]
es a
su vez una lista por lo que tiene a su ves las propiedades de estas.
Las siguientes lineas son válidas para la estructura recién definida.
for tareas in persona["experiencia_laboral"]["2005-2008"]["tareas"]:
print(f"Tarea: {tarea}")
También es posible usar dict()
para crear un diccionario.
d3 = dict(
nombre='Laura',
edad=47,
documento=221029489
)
type(d3)
# muestra <class 'dict'>
print(d3)
{'nombre': 'Laura', 'edad': 47, 'documento': 221029489}
No confundir diccionarios con set
En Python tambien se usan las llaves {}
para definir conjuntos (sets).
Por ejemplo s = {1, 2, 3, 4, 5}
no es un dictionario, es un set y
type(s)
mostrará <class 'set'>
Los sets son listas no ordenadas de elementos únicos (los duplicados se eliminan automáticamente).
Tareas
Hacer un PR con una propuesta de solución para el ejercicio 020
"""
Completar la funcion para que devuelva la "frase" pasada como parámetro
reemplazadas todas sus vocales con la "a" (o cualquier otra "vocal" que se
pase como parámetro)
"""
def cambia_vocales(frase, vocal="a"):
pass
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
assert cambia_vocales("hola") == "hala"
assert cambia_vocales("Juan Carlos") == "Jaan Carlas"
assert cambia_vocales("Pepito", "e") == "Pepete"
assert cambia_vocales(vocal="i", frase="me llamo juan") == "mi llimi jiin"
# revisar mayúsculas y minúsculas
assert cambia_vocales("HOli") == "HAla"
print('Ejercicio terminado OK')
Hacer un PR con una propuesta de solución para el ejercicio 030
"""
La siguiente funcion busca contar cuantas veces se repite cada palabra.
Por ejemplo de "Hola Juan. Hola Pedro" devuelve {"Hola": 2, "Juan.": 1, "Pedro": 1}
Tarea: Corregir el error de la función para que devuelva el resultado correcto.
Se espera que los signos de puntuacion no afecten el resultado y que las mayusculas
y minusculas no cuenten como palabras diferentes.
"""
def contar_palabras(frase):
"""
Esta funcion toma una frase y devuelve un diccionario
con una llave por cada palabra y un valor igual a la
cantidad de veces que aparece en la frase
"""
palabras = frase.split()
resultados = {}
for palabra in palabras:
if palabra in resultados.keys():
# si existe, sumarle 1
resultados[palabra] += 1
else:
# si no existe, inicializarla
resultados[palabra] = 0
return resultados
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
f1 = contar_palabras("Hola dijo Juan. Hola dijo pedro")
assert f1['Hola'] == 2
himno = "Oid mortales el grito sagrado. Libertad, libertad, libertad. Oid el ruido de rotas cadenas"
palabras_himno = contar_palabras(himno)
assert palabras_himno['Oid'] == 2
assert palabras_himno['libertad'] == 3
print('Ejercicio terminado OK')
Hacer un PR con una propuesta de solución para el ejercicio 031
"""
La siguiente funcion toma como parámetro una lista de diccionarios
y cuenta la cantidad de elementos que tiene un valor especifico en
una propiedad definida.
Por ejemplo de la lista
lista = [
{"genero": "M", "nombre": "Juan"},
{"genero": "F", "nombre": "Pablo"},
{"genero": "F", "nombre": "Juana", "apellido": "Gomez"},
{"genero": "M", "nombre": "Victor"},
{"genero": "M", "nombre": "Juan Pablo", "apellido": "Velez"},
{"genero": "F", "nombre": "Juana"},
{"genero": "F", "nombre": "Victoria"}
]
Se esperan estos posibles resultados
contar_si(lista, "genero", "M") == 3
contar_si(lista, "genero", "F") == 4
contar_si(lista, "nombre", "Juana") == 2
pero la funcion da error en algunos casos como
contar_si(lista, "apellido", "Gomez")
donde en realidad esperamos que devuelva 1
Tarea: Mejorar la función para que no de errores cuando una clave no existe
"""
def contar_si(lista, propiedad, valor):
"""
Esta funcion cuenta la cantidad de elementos (diccionarios) en "lista"
que tiene una "propiedad" con un "valor" específico.
"""
contador = 0
for elemento in lista:
if elemento[propiedad] == valor:
contador += 1
return contador
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
lista = [
{"genero": "M", "nombre": "Juan"},
{"genero": "F", "nombre": "Pablo"},
{"genero": "F", "nombre": "Juana", "apellido": "Gomez"},
{"genero": "M", "nombre": "Victor"},
{"genero": "M", "nombre": "Juan Pablo", "apellido": "Velez"},
{"genero": "F", "nombre": "Juana"},
{"genero": "F", "nombre": "Victoria"}
]
assert contar_si(lista, "genero", "M") == 3
assert contar_si(lista, "genero", "F") == 4
assert contar_si(lista, "nombre", "Juana") == 2
assert contar_si(lista, "apellido", "Gomez") == 1
assert contar_si(lista, "apellido", "Perez") == 0
print('Ejercicio terminado OK')
Hacer un PR con una propuesta de solución para el ejercicio 032
"""
El siguiente código permite crear facturas de ventas y agregar items.
El código no tiene fallas pero el cliente desea que la lista de items
no tenga productos duplicados. Si se intenta agregar un producto por
segunda vez, la función deberia darse cuenta y actualizar los valores
de ese item y no agregarlo como nuevo item.
"""
def agregar_item(factura, producto, precio_unitario, cantidad=1):
"""
Agregar un item a una factura que se pasa como parámetro
"""
precio_total = cantidad * precio_unitario
item = {
'producto': producto,
'precio_unitario': precio_unitario,
'cantidad': cantidad,
'precio_total': precio_total,
}
factura['items'].append(item)
factura['total'] += precio_total
def crear_factura():
""" Crear una factura """
factura = {
'total': 0,
'items': [] # lista de items
}
return factura
mi_factura = crear_factura()
agregar_item(mi_factura, 'Alfajor', 150, 3)
agregar_item(mi_factura, 'Turron', 53)
agregar_item(mi_factura, 'Turron', 53)
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
assert mi_factura['total'] == 556
items_en_factura = mi_factura['items']
assert len(items_en_factura) == 2
print('Ejercicio terminado OK')
Hacer un PR con una propuesta de solución para el ejercicio 041
"""
La funcion "crear_mazo_cartas_espaniolas" funciona casi bien.
Por algun motivo faltan algunas cartas.
La tarea de este ejercicio es reparar esta función para que el mazo este completo
"""
def crear_mazo_cartas_espaniolas():
palos = ['oro', 'copa', 'espada', 'basto']
mazo = []
for n in range(1, 12):
for palo in palos:
carta = {'numero': n, 'palo': palo}
mazo.append(carta)
return mazo
mazo_esp = crear_mazo_cartas_espaniolas()
print(mazo_esp)
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
assert {'numero': 10, 'palo': 'oro'} in mazo_esp
assert {'numero': 11, 'palo': 'oro'} in mazo_esp
assert {'numero': 12, 'palo': 'oro'} in mazo_esp
print('Ejercicio terminado OK')
Hacer un PR con una propuesta de solución para el ejercicio 042
"""
La funcion "crear_mazo_cartas_poker" esta incompleta y necesita ser completada para
devolver una lista de diccionarios con todas las cartas disponibles en un mazo de poker.
Nota: El ejercicio 041* ya muestra una función similar que puede usarse como ayuda
* https://github.com/avdata99/programacion-para-no-programadores/blob/master/ejercicios/ejercicio-041/ejercicio.py
"""
def crear_mazo_cartas_poker():
palos = ['pica', 'trebol', 'corazon', 'diamante']
mazo = []
# COMPLETAR la lista con un diccionario por cada carta de
# la forma {'numero': X, 'palo': Y}
# El test de la parte inferior de este archivo ayuda a validar
# el resultado esperado
return mazo
# ------------------------------------------------------------------------
# NO BORRAR O MODIFICAR LAS LINEAS QUE SIGUEN
# ------------------------------------------------------------------------
# Una vez terminada la tarea ejecutar este archivo.
# Si se ve la leyenda 'Ejercicio terminado OK' el ejercicio se considera completado.
# La instruccion "assert" de Python lanzará un error si lo que se indica a
# continuacion es falso.
# Si usas GitHub (o similares) podes hacer una nueva rama con esta solución,
# crear un "pull request" y solicitar revision de un tercero.
mazo_poker = crear_mazo_cartas_poker()
assert {'numero': 9, 'palo': 'pica'} in mazo_poker
assert {'numero': 10, 'palo': 'pica'} in mazo_poker
assert {'numero': 'J', 'palo': 'pica'} in mazo_poker
assert {'numero': 'Q', 'palo': 'pica'} in mazo_poker
assert {'numero': 'K', 'palo': 'pica'} in mazo_poker
assert {'numero': 9, 'palo': 'diamante'} in mazo_poker
assert {'numero': 10, 'palo': 'diamante'} in mazo_poker
assert {'numero': 'J', 'palo': 'diamante'} in mazo_poker
assert {'numero': 'Q', 'palo': 'diamante'} in mazo_poker
assert {'numero': 'K', 'palo': 'diamante'} in mazo_poker
print('Ejercicio terminado OK')
Algunos ejemplos de uso
data = {
'edad': 32,
'nombre': 'Juan'
}
nombre = data['nombre'] # equivalente a data.get('nombre)
edad = data['edad']
print(f'Nombre: {nombre}, edad {edad} años')
"""
data['algo-que-no-existe']
# genera un error
# KeyError: 'algo-que-no-existe'
# mientras que
data.get('algo-que-no-existe')
devuelve None
"""
# Nombre: Juan, edad 32 años
for k, v in data.items():
print(f'Item encontrado: Key:{k}, Value: {v}')
# Item encontrado: Key:edad, Value: 32
# Item encontrado: Key:nombre, Value: Juan
data = {
'edad': 32,
'nombre': 'Juan',
'educacion': {
'secundario': 'Monserrat',
'universidad': 'UNC',
}
}
nombre = data['nombre']
edad = data['edad']
universidad = data['educacion']['universidad']
print(f'Nombre: {nombre}, edad {edad} años. Universidad: {universidad}')
# Nombre: Juan, edad 32 años. Universidad: UNC
# Agregarle datos
data['ocupacion'] = 'Desarrollador'
data['educacion']['primario'] = 'San Juan'
print(data)
# {'edad': 32, 'nombre': 'Juan', 'educacion': {'secundario': 'Monserrat', 'universidad': 'UNC', 'primario': 'San Juan'}, 'ocupacion': 'Desarrollador'}
print(data.get('ocupacion'))
# 'Desarrollador'
print(data.get('NO EXISTE'))
# None
print(data.get('NO EXISTE', 'valor predeterminado'))
# valor predeterminado
# lista de diccionarios
data = {
'personas': [
{'nombre': 'Juan', 'edad': 20},
{'nombre': 'Pedro', 'edad': 30},
{'nombre': 'María', 'edad': 40},
]
}
print('PERSONAS:')
for persona in data['personas']:
nombre = persona['nombre']
edad = persona['edad']
print(f' - Nombre: {nombre}, edad {edad} años')
""" resultados
PERSONAS:
- Nombre: Juan, edad 20 años
- Nombre: Pedro, edad 30 años
- Nombre: María, edad 40 años
"""