La documentación de Python 3.2 's weakref
de WeakKeyDictionary
y WeakValueDictionary
tienen una nota en la iteración en estos contenedores módulo:iteración de forma segura sobre WeakKeyDictionary y WeakValueDictionary
Nota: Precaución: Debido a que un WeakKeyDictionary se basa en parte superior de un diccionario de Python, no debe cambiar el tamaño al iterar sobre él. Esto puede ser difícil de asegurar para un WeakKeyDictionary porque las acciones realizadas por el programa durante la iteración pueden hacer que los elementos en el diccionario desaparezcan "por arte de magia" (como un efecto secundario de la recolección de basura).
Eso parece bastante grave como una especificación del comportamiento de estos contenedores. Especialmente cuando se ejecuta código que utiliza el recolector de basura de CPython (cuando se usan estructuras de datos que contienen ciclos) o usando otra implementación de Python (por ejemplo, Jython), parece que no hay forma segura de iterar sobre estas colecciones.
¿Cómo puedo iterar con seguridad sobre estas colecciones cuando el recolector de basura puede borrar referencias en cualquier punto de mi programa? Tener una solución para CPython es mi prioridad, pero también me interesa el problema en otras implementaciones.
¿Es esta quizás una forma segura de iterar sobre un WeakKeyDictionary?
import weakref
d = weakref.WeakKeyDictionary()
...
for k, v in list(d.items()):
...
¿Por qué su primer ejemplo sería inseguro? La lista contendrá fuertes referencias a cada clave y valor, y durante la última iteración, 'k' y' v' contienen fuertes referencias a los objetos que me interesan. Por lo tanto, la lista puede ser basura incluso antes de que termine la última iteración. ¿Está bien? – Feuermurmel
Eso es como decir que 'para k, v en d.items()' es seguro, porque 'k' y' v' contienen fuertes referencias a los objetos.La iteración no es segura si, dentro del for-loop, existe la posibilidad de eliminar 'k' y' v'. Para las tareas simples, iterar sobre el 'WeakKeyDictionary' debe ser seguro. – Bakuriu
Probablemente esté malinterpretando algo, pero ¿cómo se puede eliminar la referencia de los objetos 'k' y' v'? Siempre que estas variables estén dentro del alcance y no estén sobrepasadas, los objetos a los que se hace referencia son seguros. ¿O estás hablando de eliminar todas las referencias fuertes a esos objetos durante la última iteración? Eso cambiaría el diccionario, pero no será inseguro porque no se accede al diccionario después de que la iteración haya comenzado. ¿Puedes dar un ejemplo de lo que puede salir mal durante la última iteración? – Feuermurmel