Argumentos Mutables en Funciones

Python tiene una variedad de tipos de datos, algunos de los cuales pueden modificarse después de su creación y otros no. Cuando hablamos de tipos que pueden modificarse, nos referimos a ellos como tipos "mutables". En contraste, aquellos que no pueden cambiarse se denominan tipos "inmutables".

Tipos Mutables

Los tipos mutables más comunes son las list, dict y set. Aquí hay un ejemplo de una lista:

fruits = ['apple', 'banana', 'cherry']
print(fruits, type(fruits))  # ['apple', 'banana', 'cherry'] <class 'list'>

Con una list, puedes cambiar sus elementos, agregar nuevos o eliminar los existentes:

fruits[1] = 'blueberry'       # Cambia 'banana' a 'blueberry'
fruits.append('dragonfruit')  # Agrega 'dragonfruit' al final de la lista
print(fruits)                 # ['apple', 'blueberry', 'cherry', 'dragonfruit']

Tipos Inmutables

Por otro lado, ejemplos de tipos inmutables son int, float, string y tuple. Una vez creados, no puedes cambiar su contenido. Aquí hay un ejemplo de un string:

message = 'hello'
print(message, type(message))  # hello <class 'str'>

Si intentas cambiar parte del string, Python no lo permitirá:

message[0] = 'H'  # Intentar cambiar 'h' por 'H' te dará un TypeError
¿Cómo es que int es inmutable? ¿No podemos cambiar el valor con += o -=?

Cuando hablamos de mutabilidad en Python, nos referimos a que el valor real almacenado en memoria puede ser modificado. Por ejemplo, cuando tenemos una lista, podemos cambiar un elemento de la lista y sigue siendo la misma lista en memoria.

Los enteros en Python son inmutables. Esto significa que el valor en memoria no puede ser cambiado. Si tenemos un entero, a = 5, y realizamos una operación como a += 2, podría parecer que cambiamos a. Sin embargo, lo que Python realmente hizo fue crear un nuevo objeto en memoria con un valor de 7 y actualizó a para que apunte a este nuevo objeto. El 5 original no fue cambiado en memoria, por eso los int se consideran inmutables.

a = 5
print(id(a))  # Esto imprime la ubicación en memoria de a. Digamos que es 1001

a += 2
print(a)      # Esto imprime 7
print(id(a))  # Esto imprimirá una ubicación de memoria diferente, digamos que es 1002

La función id en Python devuelve la identidad de un objeto, que es única y constante para el objeto durante su vida útil. Entonces, cuando vemos que la identidad de a cambió después de la operación a += 2, es una señal clara de que a ahora apunta a un nuevo objeto en memoria. El entero original 5 no fue cambiado, lo que confirma que los enteros son de hecho inmutables en Python.

Argumentos Mutables en Funciones

Cuando pasamos un objeto mutable (como una lista) a una función, Python le da a la función una referencia a ese objeto. Esto significa que si la función modifica el objeto mutable, esa modificación se verá también fuera de la función.

Usemos una función que recibe una lista y le agrega un elemento:

def add_item(my_list):
    my_list.append('added item')  # Agrega un nuevo elemento a la lista

shopping_list = ['apples', 'bananas', 'cherries']
print(shopping_list)  # Prints: ['apples', 'bananas', 'cherries']

# Ahora usamos la función para agregar un elemento a nuestra lista de compras
add_item(shopping_list)
print(shopping_list)  # Prints: ['apples', 'bananas', 'cherries', 'added item']

Como puedes ver, cuando imprimimos shopping_list después de llamar a la función add_item, la lista tenía un nuevo elemento. Esto sucedió aunque no modificamos directamente shopping_list fuera de la función.

Sin embargo, es importante entender que si asignas un nuevo valor a todo el objeto mutable dentro de la función, eso no afectará al objeto original. Esto se debe a que le estás dando a la variable local de la función una nueva referencia, no modificando el objeto original. Veamos un ejemplo de esto:

def change_list(my_list):
    my_list = ['entirely', 'new', 'list']  # Esto no afectará a la lista original

shopping_list = ['apples', 'bananas', 'cherries']
change_list(shopping_list)
print(shopping_list)  # Still prints: ['apples', 'bananas', 'cherries']

Aunque llamamos a la función change_list con shopping_list como argumento, el contenido de shopping_list no cambió. Eso es porque dentro de la función, my_list recibió una nueva referencia (a una lista completamente nueva), mientras que la referencia de shopping_list permaneció intacta.

La clave aquí es: cuando pasas un objeto mutable a una función en Python, recuerda que si la función cambia el objeto (como agregar un elemento a una lista), el cambio es permanente y se verá fuera de la función. Pero si le das un nuevo valor a todo el objeto dentro de la función, eso no afectará al objeto original.

To check your solution you need to sign in

Sign in to continue

Sign in to your account

By continuing, you agree to our Terms of Service and Privacy Policy.