Contenido del capítulo

En este capítulo voy a hablar de un tema algo más avanzado, pero necesario para que entiendas bien como funcionan las estructuras de datos de Python.
Hablará de la mutabilidad e inmutabilidad, la hashabilidad y los hashes y la iterabilidad.

Duración estimada de todo el contenido:
Tabla de contenidos
Logo

    Comprendiendo el comportamiento de los objetos de Python

    Recuerda que en Python los tipos de datos son objetos. Por ejemplo, str, int, list, bool, etc.

    ¡Atención! En este capítulo se habla de ciertas estructuras como diccionarios y conjuntos, los cuales no están explicados aún. No te preocupes por ello, no te has perdido nada.

    Estas estructuras son otros tipos de datos de Python, como los int, float, bool... pero más complejos.

    Los siguientes capítulos están dedicados a estas estructuras.

    Espacio publicitario

    Mutabilidad

    Los objetos mutables (cambiantes) son aquellos cuyos valores internos pueden ser modificados después de su creación.

    Algunos ejemplos de objetos mutables son: list, dict y set.

    Por ejemplo, puedo crear la siguiente lista, y modificar alguno de sus valores posteriormente:

    lista = [10, 10, 30, 40]
    
    # Reasigna el valor 20 a la posición 1 de la lista
    lista[1] = 20
    
    print(lista)
    Resultado en la consola
    [10, 20, 30, 40]

    Parte del objeto ha sido modificado, sin sustituirlo completamente por otro. Esto es lo que demuestra la mutabilidad.

    Espacio publicitario

    Inmutabilidad

    Los objetos inmutables (no cambiantes) son aquellos cuyos valores internos no pueden ser modificados después de su creación.

    Algunos ejemplos de objetos mutables son: int, float, str y tuple.

    Por ejemplo, puedo crear la siguiente tupla, pero no es posible modificar alguno de sus valores posteriormente:

    tupla = (10, 10, 30, 40)
    
    # Intenta reasignar el valor 20 a la posición 1 de la tupla
    tupla[1] = 20
    print(tupla)
    Error en la consola
    TypeError: 'tuple' object does not support item assignment
    Error de tipo: el objeto de tipo 'tupla' no admite la asignación de elementos

    No he podido modificar los valores del objeto. Esto demuestra la inmutabilidad.

    Puede que aquí tengas una duda con la inmutabilidad de los tipos de datos como son float, int o str, los cuales habrás reasignado en múltiples ocasiones.

    Realmente, no los has modificado o mutado, lo que has hecho realmente es reemplazar un objeto por otro. Observa el siguiente ejemplo:

    saludo = "Hola"
    
    print(saludo[0])
    print(saludo[1])
    print(saludo[2])
    print(saludo[3])
    Resultado en la consola
    H
    o
    l
    a

    Una cadena de caracteres tiene índice de posición, como las listas. Cada caracter puede ser accedido individualmente.

    Estas posiciones de la cadena son de solo lectura. Al ser el str inmutable, no puedes reasignar valores a una posición concreta como harías con una lista. Funcionan como las tuplas en cuanto inmutabilidad:

    saludo = "Hola"
                          
    saludo[0] = "h"
    Error en la consola
    TypeError: 'str' object does not support item assignment
    Error de tipo: el objeto de tipo 'str' no admite la asignación de elementos

    El error es el mismo que con las tuplas.

    Si que puedes reemplazar una cadena por otra, pero será realmente otra, no habrás modificado la cadena en sí. Habrás modificado el estado de la variable.

    saludo = "Hola"
    
    saludo = "Adiós"
    
    print(saludo)
    Resultado en la consola
    Adiós

    Espacio publicitario

    Hashabilidad

    Para que un objeto sea hashable, debe ser inmutable, tener un valor de hash constante en tiempo de ejecución y que sea comparable con otros objetos de su tipo para determinar si son iguales.

    En Python, un hash es un valor entero que se obtiene al aplicar la función hash() a un objeto, y se utiliza para identificar ese objeto en estructuras como diccionarios o conjuntos.
    Para que un objeto en Python sea "hashable" (es decir, que se le pueda aplicar un hash), debe cumplir dos requisitos: tener un valor inmutable y definir los métodos __hash__() y __eq__().

    Por ejemplo, los tipos inmutables de Python, como los números, cadenas, y tuplas, son hashables, lo que permite usarlos como claves en diccionarios o elementos en conjuntos. Sin embargo, los tipos mutables, como las listas o los diccionarios, no son hashables y no pueden ser usados directamente en esas estructuras.

    ¿Por qué la necesidad de un hash?

    El uso de un hash es necesario en programación para mejorar la velocidad y eficiencia al almacenar y buscar datos. Sin un hash, encontrar un elemento concreto en una lista larga de datos podría requerir revisar cada elemento uno por uno, lo cual es lento cuando la cantidad de datos es grande.

    Los hashes permiten a estructuras como diccionarios y conjuntos organizar los datos de manera que se pueda acceder a ellos casi instantáneamente, sin importar cuántos elementos haya. Cada dato se convierte en un valor de hash que apunta directamente a su ubicación en memoria, haciendo que las búsquedas y accesos sean mucho más rápidos.
    Además, los hashes también sirven para verificar la integridad de los datos y almacenar contraseñas de manera segura, ya que cualquier cambio en los datos originales genera un hash distinto.

    ¿Por qué no se pueden utilizar objetos mutables como hash?

    Los objetos mutables no pueden usarse como hash en Python porque su valor puede cambiar con el tiempo, lo cual rompería la consistencia del hash. La función hash() genera un valor único basado en el contenido del objeto, y este valor se usa para organizar y acceder rápidamente a los elementos en estructuras como diccionarios y conjuntos.
    Si el contenido de un objeto mutable cambiara después de haber sido hashado, el valor del hash ya no coincidiría con la ubicación donde se almacenó originalmente en la estructura, lo que causaría problemas para encontrar y acceder a los datos correctamente.

    Por eso, solo los objetos inmutables, que garantizan que su contenido no cambiará, son aptos para usarse como claves en diccionarios o elementos en conjuntos.

    Ver el número hash de un objeto

    Para salir de dudas de si un objeto tiene hash o no, puedes utilizar la función predefinida hash() de Python.

    En el siguiente ejemplo, vamos a comprobarlo con un str:

    saludo = "Hola"
    
    # Imprime el hash del objeto
    print(hash(saludo))
    Resultado en la consola
    7566188970113123530

    El número que aparece en la consola, es el hash que tiene el objeto (no tiene que salirte el mismo número que a mí).

    Cada vez que ejecutes el programa se asignará un hash diferente al objeto.

    Esto ocurre porque los objetos se cargan en la memoria RAM al ejecutar el programa, y al cerrarlo o terminar su ejecución, se borran.

    Ahora, comprobemos sin un objeto como una lista, que incumple la regla de inmutabilidad, tiene hash o no:

    numeros = [10, 20, 30]
    
    print(hash(numeros))
    Error en la consola
    TypeError: unhashable type: 'list'
    Error de tipo: el objeto de tipo 'list' no es hashable

    El error demuestra que el tipo de dato list, no tiene un hash, por lo tanto, no es un objeto hashable.

    Todavía es pronto para desarrollar algo más complejo con los hash, pero esto te servirá para entender mejor como funcionan los conjuntos de Python, tema que explicaré en el siguiente capítulo.

    Espacio publicitario

    Iterabilidad

    La iterabilidad es la capacidad de un objeto en ser recorrido con posiciones de índice. Por ejemplo, una lista, una tupla o una cadena, son objetos iterables, porque tienen índice de posición.

    La forma más fácil de comprobar si un objeto es iterable, es intentar utilizar su índice de posición:

    numeros = [10, 20, 30]
    
    # Imprime la posición 0 de la lista
    print(numeros[0])
    Resultado en la consola
    10

    Un objeto como un int, no es iterable. Es un objeto con un valor simple, que no tiene posiciones en un índice:

    numero = 10
    
    print(numero[0])
    Error en la consola
    TypeError: 'int' object is not subscriptable
    Error de tipo: el objeto de tipo 'int' no es subscriptible

    Lo que nos quiere indicar el error, es que este tipo de objeto no es accesible mediante índice de posición. No es iterable.

    Haz las mismas comprobaciones mostradas en este capítulo, con cualquier tipo de objeto de Python. De esa forma sabrás de qué manera funciona cada uno.

    Espacio publicitario




    Espacio publicitario




    Espacio publicitario