Especializa tu propia colección en Python


Ya hemos creado nuestro Contenedor Python (como vimos en el artículo anterior sobre cómo crear nuestra propia Colección https://jarroba.com/nuestra-propia-coleccion-en-python/ ) y queremos que se especialice ¿En qué? Pues depende de lo que necesitemos, lo mejor es conocer las posibilidades y lo que Python ya nos facilita. Como si se tratara de una aventura de elige tu propia historia existen cuatro opciones (con sus muchas variantes) a partir de Collection:

  • Una secuencia de datos añadidos uno tras otro en posiciones numeradas. Se nos vendrá a la cabeza el tipo de datos “Listado/List” típico de Python (ejemplo: [1, 2, 3] ), que pertenece a la clase especializadaSecuencia” (“Sequence”).
  • Un dato es la clave que apunta (mapea) a otro dato que es el valor. Es decir, claves que mapean valores. El tipo simple de Python es “Diccionario/Dict” (ejemplo: {“clave”: “valor”, “otra clave”: “otro valor”} ), y pertenece a la clase especializadaMapeo” (“Mapping”).
  • Un conjunto de datos tiene la bondad de guarda solo valores (sin clave, como los Listados) y sin valores duplicados (como pasa con las claves de los Diccionarios que tienen que ser únicas); además, si tenemos más de un conjunto podremos realizar operaciones de conjuntos combinándolos (por ejemplo, podemos obtener todos los valores que existan tanto en un conjunto como en otro; lo que es el resultado de la “unión” de valores de ambos conjuntos). En Python su tipo simple es “Conjunto/Set” (ejemplo: set(“valor1”, “valor2”) ), que pertenece a la clase especializada “Conjunto” (“Set”).
  • Nuestra propia Colección. Desde la clase “Colección” (“Collection”) podemos inventarnos cualquier otra que no logremos clasificar en ninguna de las anteriores.

Aunque he puesto cuatro opciones, realmente las tres primeras (Sequence, Mapping y Set) son las que necesitaremos en la gran mayoría de los casos.

¿Y por qué existen estás tres? Los creadores de Python (y de otros lenguajes de programación) llegaron a la conclusión que prácticamente todas las estructuras de datos se podían representar en Secuencias (Sequence), Mapeos (Mapping) y Conjuntos (Set) ¿Y si me invento algo diferente? Eres libre de probar y descubrir nuevas estructuras de datos que no puedan ser representados en alguno de estos tres grupos, aunque prácticamente todo se puede englobar:

  • ¿Quizá una clase que dada una clave devuelva un valor que esté guardado en un fichero? Ya sería un diccionario, un Mapeo
  • ¿Una matriz o tabla de filas y columnas? Es decir, un listado de listados, una Secuencia
  • ¿Una estructura de árbol? Una Mapeo cuyas claves sean los nodos
  • ¿Quizá la descomposición de JSON? Se puede representar como diccionarios anidados y si esta representación la creamos en una única clase podría ser perfectamente un Mapeo (Sin ir más lejos la biblioteca “json” que trae Python al pasarle un JSON en texto nos devuelve una estructura de diccionarios y listados; más información en https://docs.python.org/3.7/library/json.html).

Alguna estructura de datos podría existir que no pueda ser agrupado en alguna de los tres grupos anteriores. De cualquier manera, siempre nos quedará la posibilidad de crear una clase nosotros heredando directamente desde “Colección” (“Collection”); para todo los demás y por facilitarnos la vida, recomiendo que elijas heredar la que mejor te convenga de: Mapeo, Secuencia o Conjunto.

En el artículo anterior (https://jarroba.com/nuestra-propia-coleccion-en-python/ ) vimos algunos ejemplos que podíamos clasificar como Mapeos y será por dónde empecemos.

¿Cuál elegir?

Es importante conocer las ventajas que se heredan de cada clase: Mapeo (“Mapping”), Secuencia (“Sequence”) o Conjunto (“Set”); para no trabajar en balde al repetir alguna funcionalidad que ya exista y esté fuertemente probada. Por ejemplo, si queremos que nuestro objeto devuelva los valores en orden y sus claves sean el orden en el que se añadieron dichos valores, entonces no heredamos de “Mapping” sino de “Sequence” (como ejemplo se me ocurre crear una clase que consulte a un servidor datos que queremos que devuelva en orden, así quién use nuestra clase que hereda de “Sequence” la usará igual que un listado aunque por debajo hayamos programado que obtenga los datos desde un servidor en Internet), pues prácticamente está programado todo el comportamiento deseado y solo tendríamos centrarnos en añadir nuevo comportamiento.

A continuación una imagen comparativa de los tres para que puedas elegir correctamente (Aunque la puse en el artículo de https://jarroba.com/resumibles-hashables-en-python/ me parece importante volver a recordarla en este artículo). A la izquierda en morado represento un ejemplo de cada tipo de cada clase, a la derecha sus cualidades (decir que no son ni buenas ni malas, son las necesarias), entre dos tipos de clases represento con flechas dobles las cualidades que comparten:

La anterior imagen es un resumen. Extiendo un poco más sus cualidades.

Recuerdo la diferencia entre:

  • Valores (Values): son los datos guardados como valores en la estructura de datos.
  • Claves (Keys): para un diccionario es un dato que apunta a un valor guardado, y para una secuencia es la posición de inserción (la posición es una clave numérica que apunta al valor); sin embargo, los conjuntos no tienen claves.
  • Ítems (Items): es una tupla de ambos, es decir, con la clave y el valor.

Elementos (Elements): este término es más abstracto y solo utilizado en la teoría (es decir, NO lo puedes llamar con un “getElements()” ). Hace referencia a cualquier dato guardado del contenido de la estructura de datos de la forma que sea. Es decir, en vez de decir todo el rato “Valores y/o Claves (e/o Ítems) de la estructura de datos” se resume como “Elementos de la estructura de datos”. Lo leerás mucho al repasar teoría o documentación como por ejemplo “los elementos guardados en la estructura de datos…” (significa “las claves y/o valores guardados dentro de la estructura de datos”), o los “Elementos devueltos por la estructura de datos…” (aquí ojo que puede significar “las Claves y/o los Valores e incluso a veces engloba a los Ítems devueltos por los diferentes métodos de la estructura de datos”). Son términos tan cercanos que se confunde “Ítems” con “Elementos” y está mal confundirlos. Se puede decir que “Elementos” es la forma vaga de denominar a los términos técnicos: Valores, Claves e Ítems. Este término surge de la necesidad de nombrar de alguna a los valores que tienen dentro tanto los diccionarios, como las listas, como los conjuntos (y te puedo asegurar que es muy complicado nombrar al contenido de las estructuras de datos en conjunto, al escribir este artículo por ejemplo, pues los diccionarios tienen claves y valores, las listas valores y las claves son números autoincreméntales, y los conjuntos solo tienen valores ¿Cómo se hace referencia a todos estos contenidos de las estructuras de datos tan diferentes? Pues con “Elementos” 😊 ).

Cualidades de heredar de Mapping

  • La clave puede ser de cualquier tipo que sea inmutable (int, String, etc.), es decir que la clase del objeto herede de “Hashable” (información completa sobre “Hashables” en https://jarroba.com/resumibles-hashables-en-python/ ).
  • Los valores pueden ser de cualquier tipo, tanto mutables como inmutables (todo lo que necesitas saber de mutabilidad e inmutabilidad en https://jarroba.com/mutables-e-inmutables/), es decir, de cualquier tipo.
  • La iteración (por ejemplo, obtener los valores con un bucle “for”) por los elementos contenidos será aleatoria. Antes de lanzarte a crear una clase Mapping que guarde el orden de inserción de los elementos, indicar que existe en Python un diccionario que mantiene el orden de inserción que se llama OrderedDict (más información en https://docs.python.org/3.7/library/collections.html#collections.OrderedDict); y es más, desde Python 3.7 se garantiza el orden de inserción.
  • Comprobar si tiene una clave es muy rápido (como es una “Tabla hash” la búsqueda de una clave es inmediata, más información sobre las “Tablas Hash” en https://jarroba.com/tablas-hash-o-tabla-de-dispersion/ ).
  • Permite “vistas” sobre las claves, los valores o los ítems (sino sabes qué es esto de las vistas lo veremos más adelante, verás que es bastante útil y sencillo)

Cualidades de heredar de Sequence

  • La clave solo puede ser un número entero (int) que indica la posición de inserción del valor.
  • Los valores pueden ser tanto mutables como inmutables (de cualquier tipo).
  • La iteración por los valores contenidos será en orden de inserción de los valores, y se puede iterar a la inversa (desde el último valor insertado al primero).
  • Comprobar si tiene una clave es lento (es necesario buscar uno a uno entre todos los valores contenidos).

Cualidades de heredar de Set

  • No tiene clave, solo valores.
  • Los valores solo pueden ser inmutables y no guarda valores duplicados (exactamente igual que las claves en los diccionarios).
  • Comprobar si tiene un valor es muy rápido.
  • Permite operaciones entre conjuntos diferentes: and (o unión interna), or (o unión externa completa), xor (o resta), menor que, mayor que, diferente a, igual a, etc.

Elige de qué especializarte sabiamente

Ahora te toca a ti, te toca pensar de qué colección especializarte. Por no alargar mucho este artículo y porque cada especialización tiene sentido completo, cada especialización la explicaré es un artículo aparte. Tienes disponible en www.jarroba.com:

Comparte esta entrada en:
Safe Creative #1401310112503
Especializa tu propia colección en Python por "www.jarroba.com" esta bajo una licencia Creative Commons
Reconocimiento-NoComercial-CompartirIgual 3.0 Unported License.
Creado a partir de la obra en www.jarroba.com

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.

Uso de cookies

Este sitio web utiliza cookies para que usted tenga la mejor experiencia de usuario. Si continúa navegando está dando su consentimiento para la aceptación de las mencionadas cookies y la aceptación de nuestra política de cookies

ACEPTAR
Aviso de cookies