Clave del valor máximo

PythonPythonBeginner
Practicar Ahora

This tutorial is from open-source community. Access the source code

💡 Este tutorial está traducido por IA desde la versión en inglés. Para ver la versión original, puedes hacer clic aquí

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.


Skills Graph

%%%%{init: {'theme':'neutral'}}%%%% flowchart RL python(("Python")) -.-> python/ModulesandPackagesGroup(["Modules and Packages"]) python(("Python")) -.-> python/BasicConceptsGroup(["Basic Concepts"]) python(("Python")) -.-> python/ControlFlowGroup(["Control Flow"]) python(("Python")) -.-> python/DataStructuresGroup(["Data Structures"]) python(("Python")) -.-> python/FunctionsGroup(["Functions"]) python/BasicConceptsGroup -.-> python/comments("Comments") python/ControlFlowGroup -.-> python/conditional_statements("Conditional Statements") python/DataStructuresGroup -.-> python/tuples("Tuples") python/DataStructuresGroup -.-> python/dictionaries("Dictionaries") python/FunctionsGroup -.-> python/function_definition("Function Definition") python/FunctionsGroup -.-> python/build_in_functions("Build-in Functions") python/ModulesandPackagesGroup -.-> python/importing_modules("Importing Modules") python/ModulesandPackagesGroup -.-> python/standard_libraries("Common Standard Libraries") subgraph Lab Skills python/comments -.-> lab-13677{{"Clave del valor máximo"}} python/conditional_statements -.-> lab-13677{{"Clave del valor máximo"}} python/tuples -.-> lab-13677{{"Clave del valor máximo"}} python/dictionaries -.-> lab-13677{{"Clave del valor máximo"}} python/function_definition -.-> lab-13677{{"Clave del valor máximo"}} python/build_in_functions -.-> lab-13677{{"Clave del valor máximo"}} python/importing_modules -.-> lab-13677{{"Clave del valor máximo"}} python/standard_libraries -.-> lab-13677{{"Clave del valor máximo"}} end

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:

Code editor with key_of_max function
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 llamada key_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 incorporada max() encuentra el elemento más grande. Por defecto, si le das a max() 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 argumento key le dice a max() cómo comparar los elementos. d.get es un método de los diccionarios. Cuando llamas a d.get(alguna_clave), devuelve el valor asociado con alguna_clave. Al establecer key=d.get, le estamos diciendo a max(): "Compara los elementos en el diccionario d utilizando sus valores, no sus claves". La función max() 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ón if verifica si el diccionario d está vacío.
  • return None: Si el diccionario está vacío, no hay un valor máximo, así que devolvemos None. Esta es una forma estándar de indicar la ausencia de un valor en Python. Esto evita que la función max() 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:

  1. import unittest: Importa el marco de pruebas (testing framework).
  2. from key_of_max import key_of_max: Importa la función que queremos probar.
  3. class TestKeyOfMax(unittest.TestCase):: Define una clase de prueba. Las clases de prueba agrupan pruebas relacionadas.
  4. 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 con test_.
  5. 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 si key_of_max({'a': 4, 'b': 0, 'c': 13}) devuelve 'c', lo cual debería ser así.
  6. def test_another_case(self):: Se agregó otro caso de prueba para verificar la clave del valor máximo, que puede no ser única.
  7. 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íficamente None. Esto es importante porque self.assertEqual(..., None) podría pasar para cosas que se evalúan como None, pero en realidad no son None. assertIsNone es 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.