https://github.com/johnny-godoy/laboratorios-mds/tree/main/lab%201
¶En esta primera parte se trabajará lo escencial visto hasta el momento más un poco de programación funcional a través de frutas:
Defina las siguientes frutas como diccionarios a partir de sus características (nombre, color, tipo y si posee o no pepas):
Nombre | Tipo | Color | Pepas |
---|---|---|---|
limon | cítrica | amarillo | True |
naranja | cítrica | naranjo | True |
plátano | tropical | amarillo | False |
piña | tropical | amarillo | False |
frutilla | bosque | rojo | True |
frambuesa | bosque | rojo | True |
Agregue Piña, Frutilla y Frambuesa como diccionarios (siga los ejemplos de las frutas dadas) y luego cree un arreglo que contenga estas frutas.
limon = {
"nombre": "limón",
"tipo": "cítrica",
"color": "amarillo",
"pepas": True
}
naranja = {"nombre": "naranja",
"tipo": "cítrica",
"color": "naranjo",
"pepas": True
}
platano = {"nombre": "plátano",
"tipo": "tropical",
"color": "amarillo",
"pepas": False
}
# agregar las frutas que faltan aquí
piña = {"nombre": "piña",
"tipo": "tropical",
"color": "amarillo",
"pepas": False
}
frutilla = {"nombre": "frutilla",
"tipo": "bosque",
"color": "rojo",
"pepas": True
}
frambuesa = {"nombre": "frambuesa",
"tipo": "bosque",
"color": "rojo",
"pepas": True
}
Ahora, agregue todas las frutas a un arreglo.
# Ojo: agregue los datos en el mismo orden que aparecen en la tabla
datos = [limon, naranja, platano, piña, frutilla, frambuesa]
Este arreglo será la información con la que se trabajará durante el lab.
Elabore las siguientes funciones:
1. La función describir(datos)
que genere un arreglo con strings que describan cada fruta de la siguiente manera:
{El/La} {...} es una fruta de tipo {...} de color {...}. {Presenta/No presenta} pepas en su interior.
Por ejemplo, para el plátano se debe generar el siguiente string:
'El plátano es una fruta de tipo tropical de color amarillo. No presenta pepas en su interior.'
Indicaciones:
string[indice]
.2. La función filtrar_por_pepa(datos, tiene_pepas)
que dado un tipo de fruta y un booleano, retorne las frutas que tienen o no tienen pepas (según el valor de tiene_pepas
).
Por ejemplo, filtrar_por_pepa(datos, True)
deberá retornar un arreglo con los diccionarios de: naranja, limon, frutilla y frambuesa.
3. La función conteo_colores(datos)
que cree un diccionario que haga un conteo los colores de las frutas.
Para estos datos, la función debería retornar el siguiente diccionario:
{"amarillo": 3, "naranjo": 1, "rojo": 2}
`
def describir(datos):
descripciones = []
for fruta in datos:
nombre = fruta["nombre"]
genero = "La" if nombre[-1] == "a" else "El"
presenta_pepas = "Presenta" if fruta["pepas"] else "No presenta"
descripciones.append(f'{genero} {nombre} es una fruta de tipo {fruta["tipo"]} de color {fruta["color"]}. {presenta_pepas} pepas en su interior.')
return descripciones
def filtrar_por_pepa(datos, tiene_pepas):
return [fruta for fruta in datos if fruta["pepas"] == tiene_pepas]
def conteo_colores(datos):
conteo = {}
for fruta in datos:
try:
conteo[fruta["color"]] += 1
except KeyError:
conteo[fruta["color"]] = 1
return conteo
El código de la siguiente celda presenta tests para probar sus funciones: Si la ejecución de esta celda no les levanta ninguna excepción, entonces sus funciones están implementadas según lo requerido. Si alguna falla, entonces deberán corregir los errores mostrados. Noten que los strings, diccionarios y en general, los objetos deben ser exactamente idénticos para que el test no falle.
Ejecuten esta celda para comprobar su código:
# ---------------------------------------------------------------------
# test descripciones
# note que las frutas deben estar en igual orden para que este assert no falle.
descripciones_esperadas = [
"El limón es una fruta de tipo cítrica de color amarillo. Presenta pepas en su interior.",
"La naranja es una fruta de tipo cítrica de color naranjo. Presenta pepas en su interior.",
"El plátano es una fruta de tipo tropical de color amarillo. No presenta pepas en su interior.",
"La piña es una fruta de tipo tropical de color amarillo. No presenta pepas en su interior.",
"La frutilla es una fruta de tipo bosque de color rojo. Presenta pepas en su interior.",
"La frambuesa es una fruta de tipo bosque de color rojo. Presenta pepas en su interior.",
]
assert descripciones_esperadas == describir(datos)
# ---------------------------------------------------------------------
# test filtro
frutas_con_pepa_esperadas = [
{"nombre": "limón", "tipo": "cítrica", "color": "amarillo", "pepas": True},
{"nombre": "naranja", "tipo": "cítrica", "color": "naranjo", "pepas": True},
{"nombre": "frutilla", "tipo": "bosque", "color": "rojo", "pepas": True},
{"nombre": "frambuesa", "tipo": "bosque", "color": "rojo", "pepas": True}
]
assert frutas_con_pepa_esperadas == filtrar_por_pepa(datos, True)
# ---------------------------------------------------------------------
# test conteo
conteo_esperado = {'amarillo': 3, 'naranjo': 1, 'rojo': 2}
assert conteo_esperado == conteo_colores(datos)
Implementar las funciones de la sección anterior de forma funcional (solo las primeras 2).
def describir_funcional(datos):
def generar_descripcion(fruta):
nombre = fruta["nombre"]
genero = "La" if nombre[-1] == "a" else "El"
presenta_pepas = "Presenta" if fruta["pepas"] else "No presenta"
return f'{genero} {nombre} es una fruta de tipo {fruta["tipo"]} de color {fruta["color"]}. {presenta_pepas} pepas en su interior.'
descripciones = list(map(generar_descripcion, datos))
return descripciones
def filtrar_por_pepa_funcional(datos, tipo_de_dato):
filtrados = list(filter(lambda fruta: fruta["pepas"] == tipo_de_dato, datos))
return filtrados
assert descripciones_esperadas == describir_funcional(datos)
assert frutas_con_pepa_esperadas == filtrar_por_pepa_funcional(datos, True)
En esta parte se solicitarán un par de clases que permitirá jugar con la Programación Orientada a Objetos.
Defina la clase Electrodomestico
que implemente:
enchufado
que almacene valores booleanos. esta_enchufado(self)
que levante una excepción Exception
y que termine con la ejecución del programa cuando el atributo enchuado sea False
. La exepción debe levantar el mensaje 'Alerta ⚠️: El electrodoméstico no está enchufado'
enchufar(self)
que cambia el estado de enchufado
a True.class Electrodomestico:
def __init__(self):
self.enchufado = False
def esta_enchufado(self):
if not self.enchufado:
raise Exception('Alerta ⚠️: El electrodoméstico no está enchufado')
def enchufar(self):
self.enchufado = True
Implemente la clase Jugera
que extiende Electrodomestico
y que implemente:
bandeja
).Un método llamado agregar_ingrediente(self, nueva_fruta)
que dado una fruta, agregue esa fruta a la bandeja
.
Un método llamado listar_ingredientes(self)
que imprima (con print
) los ingredientes actuales de la bandeja
de la siguiente forma:
Ingredientes en la bandeja: frutilla, frambuesa, piña.
De lo contrario si no tiene ingredientes imprima:
`Bandeja vacía`
Hint: Investigar el método join
de un string para generar el string con los nombres de las frutas.
preparar_jugo(self)
que: self.esta_enchufado()
.bandeja
. En el caso que no haya, levantar una excepción con contenido 'Error ❌: La bandeja no tiene ingredientes.'
print
) el mensaje de advertencia 'Alerta ⚠️: El jugo puede contener restos de pepas.'
. Puede usar la función definida en la sección anterior.Jugo de {nombres de las frutas separadas por una ,} listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️.
(Hint: Usar nuevamente join
).bandeja
(es decir, eliminar todas las frutas de la bandeja).class Jugera(Electrodomestico):
def __init__(self):
super().__init__()
self.bandeja = []
def agregar_ingrediente(self, nueva_fruta):
self.bandeja.append(nueva_fruta)
def listar_ingredientes(self):
if len(self.bandeja) == 0:
print("Bandeja vacía")
else:
nombres = ", ".join(fruta["nombre"] for fruta in self.bandeja)
print(f"Ingredientes en la bandeja: {nombres}.")
def preparar_jugo(self):
self.esta_enchufado() # Cae error de no ser el caso
if len(self.bandeja) < 1:
raise Exception('Error ❌: La bandeja no tiene ingredientes.')
if len(filtrar_por_pepa(datos, True)) > 0:
print('Alerta ⚠️: El jugo puede contener restos de pepas.')
nombres = ", ".join(fruta["nombre"] for fruta in self.bandeja)
mensaje = f"Jugo de {nombres} listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️."
self.bandeja = []
return mensaje
Las siguientes celdas les permitirán probar las interacciones de esta clase. La ejecución es solo referencial y no lleva puntaje. La idea es que la utilice como guía para desarrollar la clase.
jugera = Jugera()
# Como no tenemos ingredientes, listar_ingredientes deberá imprimir 'Bandeja vacía'
jugera.listar_ingredientes()
Bandeja vacía
# Esta celda debería levantar una excepcion indicando que no está enchufada la jugera.
jugera.preparar_jugo()
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Input In [10], in <cell line: 2>() 1 # Esta celda debería levantar una excepcion indicando que no está enchufada la jugera. ----> 2 jugera.preparar_jugo() Input In [8], in Jugera.preparar_jugo(self) 16 def preparar_jugo(self): ---> 17 self.esta_enchufado() # Cae error de no ser el caso 18 if len(self.bandeja) < 1: 19 raise Exception('Error ❌: La bandeja no tiene ingredientes.') Input In [7], in Electrodomestico.esta_enchufado(self) 5 def esta_enchufado(self): 6 if not self.enchufado: ----> 7 raise Exception('Alerta ⚠️: El electrodoméstico no está enchufado') Exception: Alerta ⚠️: El electrodoméstico no está enchufado
# Enchufamos el electrodoméstico
jugera.enchufar()
# Esta celda debería levantar ina excepción informandoles que la bandeja no tiene ingredientes.
jugera.preparar_jugo()
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Input In [12], in <cell line: 2>() 1 # Esta celda debería levantar ina excepción informandoles que la bandeja no tiene ingredientes. ----> 2 jugera.preparar_jugo() Input In [8], in Jugera.preparar_jugo(self) 17 self.esta_enchufado() # Cae error de no ser el caso 18 if len(self.bandeja) < 1: ---> 19 raise Exception('Error ❌: La bandeja no tiene ingredientes.') 20 if len(filtrar_por_pepa(datos, True)) > 0: 21 print('Alerta ⚠️: El jugo puede contener restos de pepas.') Exception: Error ❌: La bandeja no tiene ingredientes.
# Agregamos algunos ingredientes
jugera.agregar_ingrediente(naranja)
jugera.agregar_ingrediente(platano)
# Y los listamos (debería imprimir: 'Ingredientes en la bandeja: naranja, plátano')
jugera.listar_ingredientes()
Ingredientes en la bandeja: naranja, plátano.
# Preparamos el jugo: 'Jugo de naranja, plátano listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️.'
jugera.preparar_jugo()
Alerta ⚠️: El jugo puede contener restos de pepas.
'Jugo de naranja, plátano listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️.'
# Una vez preparado el jugo, debería vaciarse la bandeja (imprimir Bandeja vacía)
jugera.listar_ingredientes()
Bandeja vacía
Implementar bandeja
usando una property
que permita setear una nueva_bandeja
como bandeja
según las siguientes condiciones:
nueva_bandeja
sea una lista. En caso contrario, levante una excepción.nombre
, tipo
, color
y pepas
.class Jugera(Electrodomestico):
def __init__(self):
super().__init__()
self._bandeja = []
@property
def bandeja(self):
return self._bandeja
@bandeja.setter
def bandeja(self, nueva_bandeja):
if not isinstance(nueva_bandeja, list):
raise TypeError(f"Bandeja nueva es de tipo {type(nueva_bandeja)} en vez de list.")
n = len(nueva_bandeja)
if n > 3:
raise Exception(f"Nueva bandeja es tiene {n} elementos, se espera que tenga a lo más 3.")
for fruta in nueva_bandeja:
self.agregar_ingrediente(fruta)
def agregar_ingrediente(self, nueva_fruta):
if not isinstance(nueva_fruta, dict):
raise TypeError(f"Fruta {nueva_fruta} es de tipo {type(nueva_fruta)} en vez de dict")
for llave in ("nombre", "tipo", "color", "pepas"):
if llave not in nueva_fruta.keys():
raise KeyError(f"Fruta {nueva_fruta} no tiene llave {llave}.")
self._bandeja.append(nueva_fruta)
def listar_ingredientes(self):
if len(self._bandeja) == 0:
print("Bandeja vacía")
else:
nombres = ", ".join(fruta["nombre"] for fruta in self._bandeja)
print(f"Ingredientes en la bandeja: {nombres}.")
def preparar_jugo(self):
self.esta_enchufado() # Cae error de no ser el caso
if len(self._bandeja) < 1:
raise Exception('Error ❌: La bandeja no tiene ingredientes.')
if len(filtrar_por_pepa(datos, True)) > 0:
print('Alerta ⚠️: El jugo puede contener restos de pepas.')
nombres = ", ".join(fruta["nombre"] for fruta in self._bandeja)
mensaje = f"Jugo de {nombres} listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️."
self._bandeja = []
return mensaje
Las siguientes celdas les permitirán probar las interacciones de esta clase. La ejecución es solo referencial y no lleva puntaje. La idea es que la utilice como guía para desarrollar la clase.
jugera_2 = Jugera()
jugera_2.listar_ingredientes()
Bandeja vacía
jugera_2.preparar_jugo()
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Input In [18], in <cell line: 1>() ----> 1 jugera_2.preparar_jugo() Input In [16], in Jugera.preparar_jugo(self) 35 def preparar_jugo(self): ---> 36 self.esta_enchufado() # Cae error de no ser el caso 37 if len(self._bandeja) < 1: 38 raise Exception('Error ❌: La bandeja no tiene ingredientes.') Input In [7], in Electrodomestico.esta_enchufado(self) 5 def esta_enchufado(self): 6 if not self.enchufado: ----> 7 raise Exception('Alerta ⚠️: El electrodoméstico no está enchufado') Exception: Alerta ⚠️: El electrodoméstico no está enchufado
# Enchufamos el electrodoméstico
jugera_2.enchufar()
# Esta celda debería levantar ina excepción informandoles que la bandeja no tiene ingredientes.
jugera_2.preparar_jugo()
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Input In [20], in <cell line: 2>() 1 # Esta celda debería levantar ina excepción informandoles que la bandeja no tiene ingredientes. ----> 2 jugera_2.preparar_jugo() Input In [16], in Jugera.preparar_jugo(self) 36 self.esta_enchufado() # Cae error de no ser el caso 37 if len(self._bandeja) < 1: ---> 38 raise Exception('Error ❌: La bandeja no tiene ingredientes.') 39 if len(filtrar_por_pepa(datos, True)) > 0: 40 print('Alerta ⚠️: El jugo puede contener restos de pepas.') Exception: Error ❌: La bandeja no tiene ingredientes.
# Agregamos algunos ingredientes (en este caso, como son más de 3, fallará)
jugera_2.bandeja = [naranja, platano, frutilla, limon]
--------------------------------------------------------------------------- Exception Traceback (most recent call last) Input In [21], in <cell line: 2>() 1 # Agregamos algunos ingredientes (en este caso, como son más de 3, fallará) ----> 2 jugera_2.bandeja = [naranja, platano, frutilla, limon] Input In [16], in Jugera.bandeja(self, nueva_bandeja) 14 n = len(nueva_bandeja) 15 if n > 3: ---> 16 raise Exception(f"Nueva bandeja es tiene {n} elementos, se espera que tenga a lo más 3.") 17 for fruta in nueva_bandeja: 18 self.agregar_ingrediente(fruta) Exception: Nueva bandeja es tiene 4 elementos, se espera que tenga a lo más 3.
# Agregamos algunos ingredientes
# (en este caso debería fallar, ya que estamos entregando un string en el primer lugar)
jugera_2.bandeja = ["naranja", platano, frutilla]
--------------------------------------------------------------------------- TypeError Traceback (most recent call last) Input In [22], in <cell line: 3>() 1 # Agregamos algunos ingredientes 2 # (en este caso debería fallar, ya que estamos entregando un string en el primer lugar) ----> 3 jugera_2.bandeja = ["naranja", platano, frutilla] Input In [16], in Jugera.bandeja(self, nueva_bandeja) 16 raise Exception(f"Nueva bandeja es tiene {n} elementos, se espera que tenga a lo más 3.") 17 for fruta in nueva_bandeja: ---> 18 self.agregar_ingrediente(fruta) Input In [16], in Jugera.agregar_ingrediente(self, nueva_fruta) 20 def agregar_ingrediente(self, nueva_fruta): 21 if not isinstance(nueva_fruta, dict): ---> 22 raise TypeError(f"Fruta {nueva_fruta} es de tipo {type(nueva_fruta)} en vez de dict") 23 for llave in ("nombre", "tipo", "color", "pepas"): 24 if llave not in nueva_fruta.keys(): TypeError: Fruta naranja es de tipo <class 'str'> en vez de dict
# Agregamos algunos ingredientes
# (en este caso debería fallar, ya que arándando tiene solo la llave nombre)
jugera_2.bandeja = [{'nombre': 'arándano'}, platano, frutilla]
--------------------------------------------------------------------------- KeyError Traceback (most recent call last) Input In [23], in <cell line: 3>() 1 # Agregamos algunos ingredientes 2 # (en este caso debería fallar, ya que arándando tiene solo la llave nombre) ----> 3 jugera_2.bandeja = [{'nombre': 'arándano'}, platano, frutilla] Input In [16], in Jugera.bandeja(self, nueva_bandeja) 16 raise Exception(f"Nueva bandeja es tiene {n} elementos, se espera que tenga a lo más 3.") 17 for fruta in nueva_bandeja: ---> 18 self.agregar_ingrediente(fruta) Input In [16], in Jugera.agregar_ingrediente(self, nueva_fruta) 23 for llave in ("nombre", "tipo", "color", "pepas"): 24 if llave not in nueva_fruta.keys(): ---> 25 raise KeyError(f"Fruta {nueva_fruta} no tiene llave {llave}.") 26 self._bandeja.append(nueva_fruta) KeyError: "Fruta {'nombre': 'arándano'} no tiene llave tipo."
# Agregamos algunos ingredientes (en este caso, como son 3, debería funcionar)
jugera_2.bandeja = [naranja, platano, frutilla]
# Y los listamos (debería imprimir: 'Ingredientes en la bandeja: naranja, plátano')
jugera_2.listar_ingredientes()
Ingredientes en la bandeja: naranja, plátano, frutilla.
# Una vez preparado el jugo, imprima el contenido del jugo y si una alerta,
# en el caso que el jugo tenga pepas.
jugera_2.preparar_jugo()
Alerta ⚠️: El jugo puede contener restos de pepas.
'Jugo de naranja, plátano, frutilla listo. 🏖️🥤 Que lo disfrutes!!! 🥤🏖️.'
jugera_2._bandeja
[]