python - sumar - Modificar la lista y el diccionario durante la iteración
restar tiempo python (2)
Creo que la razón es simple. list
s se ordenan, dict
s (antes de Python 3.6 / 3.7) y set
s no. Por lo tanto, la modificación de una list
a medida que itera puede no ser recomendada como la mejor práctica, pero conduce a un comportamiento consistente, reproducible y garantizado .
Podría usar esto, por ejemplo, digamos que quería dividir una list
con un número par de elementos a la mitad e invertir la segunda mitad:
>>> lst = [0,1,2,3]
>>> lst2 = [lst.pop() for _ in lst]
>>> lst, lst2
([0, 1], [3, 2])
Por supuesto, hay formas mucho mejores e intuitivas de realizar esta operación, pero el punto es que funciona.
Por el contrario, el comportamiento para dict
s y set
s es totalmente específico de la implementación ya que el orden de iteración puede cambiar dependiendo del hash.
RunTimeError
con collections.OrderedDict
, presumiblemente por coherencia con el comportamiento dict
. No creo que haya ningún cambio en el comportamiento del dict
después de Python 3.6 (donde los dict
s están garantizados para mantener la inserción ordenada) ya que rompería la compatibilidad con versiones anteriores para casos de uso no real.
Tenga en cuenta que collections.deque
también genera un RuntimeError
en este caso, a pesar de estar ordenado.
Consideremos este código
x = list(range(5))
for i in x:
print(i)
x.pop()
Imprimirá
0
1
2
Solo se imprimen los tres primeros elementos ya que los dos últimos elementos de la lista se eliminaron en las dos primeras iteraciones.
Ahora considera esto
y = {i: i for i in range(5)}
for i in y:
print(i)
y.pop(i)
Imprimirá 0
, luego aumentar RuntimeError: dictionary changed size during iteration
, porque estamos eliminando una clave del diccionario mientras iteramos sobre ella.
Por supuesto, modificar una lista durante la iteración es malo. Pero ¿por qué no se RuntimeError
un RuntimeError
como en el caso del diccionario? ¿Hay alguna buena razón para este comportamiento?
El diccionario utiliza el orden de inserción con un nivel adicional de direccionamiento indirecto, lo que causa contratiempos cuando se itera mientras se quitan las claves y se vuelven a insertar, cambiando así el orden y los punteros internos del diccionario.
Y este problema no se soluciona al iterar d.keys()
lugar de d
, ya que en Python 3, d.keys()
devuelve una vista dinámica de las claves en el dict
que da como resultado el mismo problema. En su lugar, itere sobre la list(d)
ya que esto producirá una lista de las teclas del diccionario que no cambiará durante la iteración