Versión: 3.4+
Introducción
Una enumeración es un conjunto de valores constantes representados por un nombre. Generalmente los valores no se repiten, aunque éste no es siempre el caso; y la sintáxis es la siguiente:
enumeración.miembro
En donde enumeración
es el nombre de la misma, mientras que miembro
es justamente éso, un método de la clase que representa un valor. Por ejemplo:
if respuesta == respuestas.si: cargar() elif respuesta == respuestas.no: salir()
En este caso respuestas
es la enumeración y si
y no
son dos de sus miembros. Generalmente los valores representados por cada miembro son numéricos, pero también pueden tratarse de cadenas o cualquier otro valor.
Hasta la versión 3.3 las enumeraciones han dado que hablar, sobretodo para programadores que migraban desde otros lenguajes que las integraban por defecto. De todas maneras, siempre fue posible implementar de algún u otro modo las enumeraciones en versiones anteriores a la 3.4. Tan solo véase esta pregunta en StackOverflow en donde se discute acerca de ello y se presentan gran cantidad de ejemplos y alternativas.
A partir de Python 3.4 el lenguaje implementa enumeraciones de forma nativa, por defecto, vía el módulo enum
. En efecto, presenta una extensa documentación que incluye una descripción completa y con ejemplos. Si quieres saber aún más, puedes darle una leída al PEP 435 — Adding an Enum type to the Python standard library, en el que se indican los motivos de la estandarización, descripción, uso, y más.
El módulo enum
Como dije anteriormente, ahora las enumeraciones se encuentran estandarizadas por el módulo enum
. Éste exporta tres objetos: Enum
, IntEnum
y unique
. Un ejemplo de una enumeración haciendo uso del módulo es el siguiente:
from enum import Enum class Color(Enum): rojo = 1 verde = 2 azul = 3
Las enumeraciones se crean como cualquier otra clase, heredando desde Enum
o IntEnum
(ver más adelante) lo que permite una rápida y fácil interpretación.
Antes de comenzar con la descripción, voy a citar la nota Nomenclature (Nomenclatura) de la documentación oficial, para que te familiarices con el lenguaje.
- La clase
Color
es una enumeración (o enum)- Los atributos
Color.rojo
,Color.verde
, etc., son miembros de la enumeración.- Los miembros de la enumeración tienen nombres y valores (el nombre de
Color.rojo
esrojo
, el valor deColor.azul
es3
, etc.)
Recuerda esto de ahora en más para la compresión de lo siguiente.
Enum
De todos los tres objetos exportados, se trata de la clase base. Podrás crear tus enumeraciones heredando de ésta, como en el ejemplo anterior. Teniendo en cuenta el ejemplo en la introducción, podría definirse de la siguiente manera (asumiendo que ya has importado Enum
):
class Respuestas(Enum): si = 1 no = 2
Y accederás a sus miembros utilizando, por ejemplo, Respuestas.si
, Respuestas.no
, etc.
Si acaso quieres mostrar en pantalla algún miembro de la enumeración, simplemente:
>>> print(Respuestas.si) Respuestas.si >>> str(Respuestas.si) 'Respuestas.si'
Estarás pensando, seguramente, por qué al imprimir en pantalla o convertir a una cadena la enumeración no muestra su valor. La respuesta es que los miembros de las enumeraciones no son enteros (int
), como tampoco cadenas (str
), o números de coma flotante (float
), sino objetos que contienen un nombre y un valor.
>>> Respuestas.si.name 'si' >>> Respuestas.no.name 'no' >>> Respuestas.si.value 1 >>> Respuestas.no.value 2
Las enumeraciones, como también dije anteriormente, pueden contener otros valores no numéricos. Algunos ejemplos:
class Abecedario(Enum): vocales = "aeiou" consonantes = "bcdfghjklmnñpqrstvwqyz" cantidad_letras = 27 >>> Abecedario.vocales <Abecedario.vocales: 'aeiou'> >>> Abecedario.vocales.name 'vocales' >>> Abecedario.vocales.value 'aeiou' >>> Abecedario.cantidad_letras <Abecedario.cantidad_letras: 27> >>> Abecedario.cantidad_letras.name 'cantidad_letras' >>> Abecedario.cantidad_letras.value 27
Reglas generales
Además de las comentadas anteriormente, debes conocer las siguientes propiedades de las enumeraciones.
Iteración
Puedes iterar entre los miembros de una enumeración. Por ejemplo:
>>> for miembro in Abecedario ... print(miembro) ... print(miembro.name) ... print(miembro.value) ... Abecedario.vocales vocales aeiou Abecedario.consonantes consonantes bcdfghjklmnñpqrstvwqyz Abecedario.cantidad_letras cantidad_letras 27
Acceso
Puedes acceder a un miembro de la enumeración por su nombre, al estilo de los diccionarios. Por ejemplo:
>>> Abecedario["vocales"] <Abecedario.vocales: 'aeiou'> >>> miembro = "cantidad_letras" >>> Abecedario[miembro].value 27
También puedes especificar un valor determinado para obtener el miembro correspondiente:
>>> Abecedario(27) <Abecedario.cantidad_letras: 27> >>> Abecedario("aeiou") <Abecedario.vocales: 'aeiou'>
Miembros y valores
Una enumeración no puede tener dos miembros del mismo nombre, por ejemplo:
>>> class Hardware(Enum): ... teclado = 1 ... teclado = 2 ... Traceback (most recent call last): TypeError: Attempted to reuse key: 'teclado'
Pero en muchas ocasiones es útil tener dos o más miembros con el mismo valor, lo cual sí está permitido:
class Hardware(Enum): teclado = 1 mouse = 2 raton = 2
Comparaciones
Las enumeraciones preferiblemente deben ser comparadas con la palabra reservada is
o, en su término negativo, is not
. Por ejemplo:
>>> Hardware.mouse is Hardware.raton True >>> Hardware.mouse is Hardware.teclado False >>> Hardware.teclado is Hardware.teclado True
Aunque también pueden utilizarse los operadores ==
y !=
:
>>> Hardware.teclado == Hardware.teclado True >>> Hardware.mouse == Hardware.mouse True >>> Hardware.raton == Hardware.teclado False >>> Hardware.raton != Hardware.mouse False
No intentes comparar enumeraciones heredadas de únicamente Enum
con su respectivo valor, siempre retornará False
:
>>> Hardware.raton == 2 False >>> Hardware.mouse == 2 False >>> Hardware.teclado == 1 False
IntEnum
IntEnum es una clase que hereda de Enum
y, a su vez, de int
. De esta manera puedes realizar comparaciones número-valor directamente. Veamos un ejemplo:
>>> Implementaciones.cpython == 1 True >>> Implementaciones.pypy == 2 True >>> Implementaciones.stackless < Implementaciones.cpython False >>> Implementaciones.pypy > Implementaciones.cpython True
En este caso, los valores de los miembros sí son números enteros (al momento de realizar comparaciones). Un comportamiento idéntico pudo haberse obtenido delcarando la enumeración de la siguiente manera:
>>> class Implementaciones(int, Enum): ... cpython = 1 ... pypy = 2 ... stackless = 3 ... >>> Implementaciones.pypy < Implementaciones.stackless True
Teniendo en cuenta esto, puedes crear tus enumeraciones con el tipo que desees:
>>> class Constantes(float, Enum): ... pi = 3.14 ... e = 2.17 ... >>> Constantes.pi > Constantes.e True >>> Constantes.pi <Constantes.pi: 3.14> >>> Constantes.e <Constantes.e: 2.17>
unique
Puedes utilizar el decorador enum.unique
para restringir el uso de valores duplicados:
>>> from enum import Enum, unique >>> >>> @unique ... class Hardware(Enum): ... teclado = 1 ... mouse = 2 ... raton = 2 ... Traceback (most recent call last): ValueError: duplicate values found in <enum 'Hardware'>: raton -> mouse
Más
Si aún tienes ganas de más sobre enumeraciones, puedes consultar la documentación.
Curso online 👨💻
¡Ya lanzamos el curso oficial de Recursos Python en Udemy!
Un curso moderno para aprender Python desde cero con programación orientada a objetos, SQL y tkinter
en 2024.
Consultoría 💡
Ofrecemos servicios profesionales de desarrollo y capacitación en Python a personas y empresas. Consultanos por tu proyecto.