Introducción
En Python, los diccionarios son una estructura de datos útil que te permite almacenar pares clave-valor. A veces, es posible que necesites encontrar la clave del valor máximo en un diccionario. En este reto, escribirás una función que tome un diccionario como argumento y devuelva la clave del valor máximo en el diccionario.
Creación de la función básica
Comencemos por crear el núcleo de nuestra función. La construiremos paso a paso. Primero, crea un archivo llamado key_of_max.py. Puedes utilizar el editor de código incorporado de LabEx, o un editor basado en terminal como nano o vim. Dentro de key_of_max.py, agrega el siguiente código:

def key_of_max(d):
"""
Devuelve la clave asociada con el valor máximo en el diccionario 'd'.
Si múltiples claves comparten el valor máximo, cualquiera de ellas puede ser devuelta.
"""
return max(d, key=d.get)
A continuación, una desglose:
def key_of_max(d):: Esto define una función llamadakey_of_max. Toma un argumento,d, que representa el diccionario con el que trabajaremos.return max(d, key=d.get): Este es el corazón de la función. Analicémoslo parte por parte:max(d,...): La función incorporadamax()encuentra el elemento más grande. Por defecto, si le das amax()un diccionario, encontrará la clave más grande (alfabéticamente). No queremos eso; queremos la clave asociada con el valor más grande.key=d.get: Esta es la parte crucial. El argumentokeyle dice amax()cómo comparar los elementos.d.getes un método de los diccionarios. Cuando llamas ad.get(alguna_clave), devuelve el valor asociado conalguna_clave. Al establecerkey=d.get, le estamos diciendo amax(): "Compara los elementos en el diccionariodutilizando sus valores, no sus claves". La funciónmax()luego devuelve la clave correspondiente a ese valor máximo.
Manejo del caso del diccionario vacío
Nuestra función actual tiene un problema: se romperá si el diccionario de entrada d está vacío. Arreglemos eso. Modifica key_of_max.py para que se vea así:
def key_of_max(d):
"""
Devuelve la clave asociada con el valor máximo en el diccionario 'd'.
Si múltiples claves comparten el valor máximo, cualquiera de ellas puede ser devuelta.
"""
if not d: ## Check if the dictionary is empty
return None
return max(d, key=d.get)
Las líneas agregadas hacen lo siguiente:
if not d:: En Python, un diccionario vacío se considera "falso" (falsy). Esta declaraciónifverifica si el diccionariodestá vacío.return None: Si el diccionario está vacío, no hay un valor máximo, así que devolvemosNone. Esta es una forma estándar de indicar la ausencia de un valor en Python. Esto evita que la funciónmax()lance un error.
Este es un paso crucial al escribir código robusto: ¡siempre considera los casos extremos (edge cases)!
Creación de pruebas unitarias: Pruebas básicas
Ahora, escribamos algunas pruebas para asegurarnos de que nuestra función funcione correctamente. Usaremos el módulo unittest de Python. Crea un nuevo archivo llamado test_key_of_max.py y agrega el siguiente código:
import unittest
from key_of_max import key_of_max ## Import our function
class TestKeyOfMax(unittest.TestCase):
def test_basic_case(self):
self.assertEqual(key_of_max({'a': 4, 'b': 0, 'c': 13}), 'c')
def test_another_case(self):
self.assertEqual(key_of_max({'apple': 10, 'banana': 5, 'orange': 10}), 'apple')
if __name__ == '__main__':
unittest.main()
Explicación:
import unittest: Importa el marco de pruebas (testing framework).from key_of_max import key_of_max: Importa la función que queremos probar.class TestKeyOfMax(unittest.TestCase):: Define una clase de prueba. Las clases de prueba agrupan pruebas relacionadas.def test_basic_case(self):: Define un método de prueba. Cada método de prueba verifica un aspecto específico de nuestra función. Los nombres de los métodos de prueba deben comenzar contest_.self.assertEqual(...): Esta es una afirmación (assertion). Verifica si dos valores son iguales. Si no son iguales, la prueba falla. En este caso, estamos verificando sikey_of_max({'a': 4, 'b': 0, 'c': 13})devuelve'c', lo cual debería ser así.def test_another_case(self):: Se agregó otro caso de prueba para verificar la clave del valor máximo, que puede no ser única.if __name__ == '__main__': unittest.main(): Este es un patrón estándar de Python que ejecuta las pruebas cuando se ejecuta el script directamente (por ejemplo,python3 test_key_of_max.py).
Ejecuta las pruebas desde tu terminal: python3 test_key_of_max.py. Deberías ver una salida que indique que las dos pruebas pasaron.
python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
Prueba del diccionario vacío (caso extremo)
Agreguemos una prueba específicamente para el caso del diccionario vacío. Agrega este método a tu clase TestKeyOfMax en test_key_of_max.py:
def test_empty_dictionary(self):
self.assertIsNone(key_of_max({}))
self.assertIsNone(...): Esta afirmación (assertion) verifica si el valor es específicamenteNone. Esto es importante porqueself.assertEqual(..., None)podría pasar para cosas que se evalúan comoNone, pero en realidad no sonNone.assertIsNonees más estricto.
Ejecuta las pruebas nuevamente (python3 test_key_of_max.py). Las tres pruebas (las dos pruebas básicas y la prueba del diccionario vacío) ahora deberían pasar.
python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 3 tests in 0.000s
OK
Prueba con valores negativos
Como prueba final, manejemos un caso en el que todos los valores en el diccionario son negativos. Agrega este método a TestKeyOfMax:
def test_all_negative_values(self):
self.assertEqual(key_of_max({'x': -5, 'y': -2, 'z': -10}), 'y')
Esta prueba asegura que nuestra función identifique correctamente el valor menos negativo (que es el máximo en este caso) y devuelva su clave asociada.
Ejecuta tus pruebas una última vez (python3 test_key_of_max.py). Las cuatro pruebas deben pasar. Esto nos da una alta confianza de que nuestra función está funcionando correctamente.
Tu archivo test_key_of_max.py completo ahora debería verse así:
import unittest
from key_of_max import key_of_max
class TestKeyOfMax(unittest.TestCase):
def test_basic_case(self):
self.assertEqual(key_of_max({'a': 4, 'b': 0, 'c': 13}), 'c')
def test_another_case(self):
self.assertEqual(key_of_max({'apple': 10, 'banana': 5, 'orange': 10}), 'apple')
def test_empty_dictionary(self):
self.assertIsNone(key_of_max({}))
def test_all_negative_values(self):
self.assertEqual(key_of_max({'x': -5, 'y': -2, 'z': -10}), 'y')
if __name__ == '__main__':
unittest.main()
Ejecuta las pruebas nuevamente (python3 test_key_of_max.py). Las cuatro pruebas deben pasar. Esto nos da una alta confianza de que nuestra función está funcionando correctamente.
python3 test_key_of_max.py
----------------------------------------------------------------------
Ran 4 tests in 0.000s
OK
Resumen
En este laboratorio, construiste una función de Python, key_of_max, para encontrar la clave asociada con el valor más grande en un diccionario. Aprendiste cómo usar la función max() con un argumento key personalizado, y manejaste el importante caso extremo (edge case) de un diccionario vacío. También escribiste pruebas unitarias exhaustivas utilizando el módulo unittest, cubriendo casos básicos, diccionarios vacíos y diccionarios con todos los valores negativos. Esta combinación de código funcional y pruebas exhaustivas demuestra buenas prácticas de desarrollo de software.