Python Quiz 2 – Modificación de elementos de listas iterando en Python

PyQuiz 2 - modificacion de elementos en listas iterando

Pregunta principal del pyquiz:

>>> lst = [1, 2, 3, 4, 5, 6]
>>> acc = 0
>>> for x in lst:
...     acc += x
...     lst.remove(x)
...
>>> print(acc)
- ?? -
# A - 21
# B - 9
# C - RuntimeError

Concepto y explicación

Esta pregunta esconde uno de los problemas más escondidos a la hora de trabajar con listas, el cambio de elementos mientras se itera sobre la propia lista.

Este problema suele ser típico de que ocurra dado que no eleva ninguna excepción y el código es totalmente valido, salvo que cuando se ejecuta el resultado es muy peculiar.

El concepto del código en general es:

  • Partimos de una lista de elementos numéricos.
  • Se inicializa una variable tipo acumulador.
  • Se itera por los elementos de la lista.
  • En cada iteración se suma el valor del elemento a la variable acumuladora.
  • Tras la actualización, se elimina el valor de la lista.
  • Al final de la ejecución se imprime por pantalla el valor de la variable acumuladora.

A simple vista se podría asumir que el resultado es igual que el sumatorio de todos los elementos:

>>> sum([1, 2, 3, 4, 5, 6])
21

Pero al ejecutar el código se ve que la respuesta correcta es 9, pero ¿¿Cómo puede ser?? razonemos el porqué.

Por un lado, internamente los bucles for tienen una variable que indica la posición en la que se encuentra iterando que es similar a hacer un range(len(lst)).

Por otro lado, cuando el índice es mayor que la lista o se llega al final de la lista se para la ejecución.

Por lo tanto en este caso irá desde el 0 hasta que no haya más elementos, sin embargo en este caso se están eliminando elementos de la lista, sin tener en cuenta este índice interno, por lo que se producen «saltos de elementos«.

A continuación se muestran las iteraciones internas del bucle con el índice interno:

# acc = 0, lst = [1, 2, 3, 4, 5, 6], idx = 0
>>> for x in lst:  # x == 1
...     acc += x   # acc == 1
...     lst.remove(x)
...
# acc = 1, lst = [2, 3, 4, 5, 6], idx = 1
>>> for x in lst:  # x == 3
...     acc += x   # acc = 4
...     lst.remove(x)
...
# acc = 4, lst = [2, 4, 5, 6], idx = 2
>>> for x in lst:  # x == 5
...     acc += x   # acc = 9
...     lst.remove(x)
...
# acc = 9, lst = [2, 4, 6], idx = 3
>>> for x in lst:  # idx > len(lst) -> fin de iteraciones
...     acc += x
...     lst.remove(x)
...

Como se puede ver, en vez de hacer 6 iteraciones, la ejecución termina en la cuarta iteración dado que el índice interno del bucle es mayor que el número de elementos que quedan (no existe elementos en la posición lst[3]).

El acumulador queda como 9 y la lista lst como [2, 4, 6].

Este suele ser un problema difícil de depurar y fácilmente reproducible, por lo que recuerda: nunca se cambian los elementos de un iterador que se esté usando, siempre hay que hacer una copia o eliminar los elementos tras iterar.

Solución

Por tanto la solución correcta es la B, dado que el acumulador queda con el valor 9.

B) 9


Practica Python con PyQuizzes

En la sección de PyQuizzes puedes encontrar ejercicios prácticos explicados pormenorizado para mejorar tus habilidades como pythonista. ¡No te los pierdas!


Tutorial Python online

Aprender Python de forma gratuita siguiendo las secciones del tutorial de Python.


Libros recomendados para aprender Python

Estos son los libros que pueden ayudarte a aprender Python, aprender a programar, tipos de datos, algoritmia y mucho más.

Disponible en:

Compartir

1 respuesta

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

Ver más

  • Responsable: Oscar Ramirez.
  • Finalidad:  Moderar los comentarios.
  • Legitimación:  Por consentimiento del interesado.
  • Destinatarios y encargados de tratamiento: No se ceden o comunican datos a terceros para prestar este servicio. El Titular ha contratado los servicios de alojamiento web a ionos (1&1) que actúa como encargado de tratamiento.
  • Derechos: Acceder, rectificar y suprimir los datos.
  • Información Adicional: Puede consultar la información detallada en la Política de Privacidad.

Publicar un comentario