Mutable e Inmutable en Python

Mutable e Inmutable en Python

Este artículo explica mutable e inmutable en Python.

YouTube Video

Mutable e Inmutable en Python

"Mutable" e "inmutable" se refieren a la mutabilidad de un objeto. Comprender esto ayuda a evitar errores inesperados y a manejar la memoria de manera eficiente.

¿Qué es Mutable?

Los objetos mutables pueden cambiar su estado interno después de ser creados.

Principales Tipos de Datos Mutables

  • list
  • dict
  • set
  • Clases definidas por el usuario (si sus atributos pueden ser modificados)

Ejemplo: Modificar una Lista

1numbers = [1, 2, 3]
2numbers[0] = 100
3print(numbers)  # [100, 2, 3]

Una lista es un objeto mutable y sus elementos se pueden modificar libremente.

¿Qué es Inmutable?

Los objetos inmutables no pueden ser modificados una vez que son creados. Intentar modificarlos resulta en la creación de un nuevo objeto.

Principales Tipos de Datos Inmutables

  • int
  • float
  • str
  • tuple
  • bool
  • frozenset

Ejemplo: Modificar un String

1text = "hello"
2# text[0] = "H"  # TypeError: 'str' object does not support item assignment
3
4text = "H" + text[1:]  # Creates a new string
5print(text)  # "Hello"

Los strings son inmutables, por lo que no puedes modificarlos parcialmente.

Comparación de Mutable e Inmutable

 1# Mutable example
 2a = [1, 2, 3]
 3b = a
 4b[0] = 100
 5print(a)  # [100, 2, 3] -> a is also changed
 6
 7# Immutable example
 8x = 10
 9y = x
10y = 20
11print(x)  # 10 -> x is unchanged

Como puedes ver en este ejemplo, los objetos mutables se comparten por referencia, por lo que pueden afectar a otras variables. Por otro lado, los objetos inmutables crean nuevas instancias al reasignarse, dejando el valor original sin afectar.

Inspección del Comportamiento Interno Usando id()

En Python, puedes usar la función id() para verificar el ID de un objeto. El ID del objeto es similar a una dirección de memoria.

 1# Immutable int behavior
 2a = 10
 3print(id(a))  # e.g., 140715920176592
 4a += 1
 5print(id(a))  # e.g., 140715920176624 -> ID has changed
 6
 7# Mutable list behavior
 8b = [1, 2, 3]
 9print(id(b))  # e.g., 2819127951552
10b.append(4)
11print(id(b))  # Same ID -> only the content has changed

Como se muestra, se crea un nuevo objeto para tipos inmutables, mientras que los tipos mutables se modifican en su lugar.

Funciones y Precaución con Objetos Mutables e Inmutables

Al pasar un objeto mutable a una función, los datos originales pueden ser modificados.

Ejemplo: Una Función que Modifica una Lista

1def modify_list(lst):
2    lst.append(100)
3
4my_list = [1, 2, 3]
5modify_list(my_list)
6print(my_list)  # [1, 2, 3, 100]

Ejemplo: Una Función que Modifica un Número

Por otro lado, intentar modificar un objeto inmutable resulta en la creación de un nuevo objeto.

1def modify_number(n):
2    n += 10
3
4my_number = 5
5modify_number(my_number)
6print(my_number)  # 5 -> unchanged

Consideraciones Prácticas

Evita Usar Objetos Mutables como Argumentos por Defecto

 1# Bad example
 2def add_item(item, container=[]):
 3    container.append(item)
 4    return container
 5
 6print(add_item(1))  # [1]
 7print(add_item(2))  # [1, 2] -> unintended behavior
 8
 9# Good example
10def add_item(item, container=None):
11    if container is None:
12        container = []
13    container.append(item)
14    return container
15
16print(add_item(1))  # [1]
17print(add_item(2))  # [2]

Dado que los argumentos por defecto se evalúan solo una vez al definir la función, el uso de objetos mutables puede conducir a efectos secundarios inesperados.

  • En el primer ejemplo, se utiliza el mismo objeto de lista cada vez que se llama a add_item. Al llamar a add_item(2) por segunda vez, el 1 añadido anteriormente todavía está en la lista, lo que da como resultado [1, 2].
  • En el ejemplo mejorado, se usa None como valor predeterminado y se crea una nueva lista dentro de la función si el argumento es None. Esto asegura que se cree una nueva lista cada vez que se llama a la función, por lo que los resultados anteriores no afectan las llamadas posteriores.

Evita usar objetos mutables como listas o diccionarios como argumentos predeterminados; en su lugar, usa None e inicialízalos dentro de la función. Esta es una práctica recomendada fundamental e importante en Python.

Resumen

Para comprender profundamente las variables y tipos de datos de Python, es crucial entender las diferencias entre mutables e inmutables. Comprender estas características te ayuda a evitar comportamientos no deseados en tu código y a escribir programas más robustos y legibles.

Puedes seguir el artículo anterior utilizando Visual Studio Code en nuestro canal de YouTube. Por favor, también revisa nuestro canal de YouTube.

YouTube Video