print dict dictionary iterator language-features python-3.x

dictionary - dict - keyerror python



Python 3.0-los métodos dict devuelven vistas-¿por qué? (3)

De hecho estás obteniendo una lista. Simplemente no es una copia de la lista interna, sino algo que actúa como si fuera una lista, pero solo representa el estado interno.

Es la misma manera que se implementa en Java (y probablemente en muchos otros lenguajes / entornos).

La razón principal es que, para muchos casos de uso, devolver una lista completamente separada es innecesario y derrochador. Requeriría copiar todo el contenido (que puede o no ser mucho).

Si simplemente desea iterar sobre las teclas, entonces no es necesario crear una nueva lista. Y si realmente lo necesita como una lista separada (como una copia), entonces puede crear fácilmente esa lista desde la vista.

Los métodos dict dict.keys (), dict.items () y dict.values ​​() devuelven "vistas" en lugar de listas. http://docs.python.org/dev/3.0/whatsnew//3.0.html

Antes que nada, ¿cómo es una vista diferente de un iterador? En segundo lugar, ¿cuál es el beneficio de este cambio? ¿Es solo por razones de rendimiento?

No me parece intuitivo, es decir, estoy pidiendo una lista de cosas (dame todas tus llaves) y me devuelven algo más. ¿Esto confundirá a la gente?


Como ya se mencionó en la pregunta relacionada, view tiene el método len() , que el iterador no tiene (pero la lista lo tiene).

Otro beneficio de devolver una vista en lugar de una lista es que, al menos para las claves, tiene una prueba de pertenencia optimizada en O (1) operaciones en lugar de O (N) para la lista (o iterador).


La respuesta de Joachim Sauer explica muy bien por qué no se devuelve una list . Pero esto deja la pregunta de por qué estas funciones no devolverían iteradores, al igual que iteritems etc. en Python 2.

Un iterador es mucho más restrictivo que un contenedor. Por ejemplo, un iterador no permite más de una pasada; si intenta un segundo pase, verá que está vacío. Por lo tanto, operaciones como elem in cont son compatibles con contenedores, pero no pueden ser compatibles con iteradores: una vez que se comprueba si un elemento está "en" el iterador, el iterador se destruye.

Por otro lado, para obtener un contenedor generalmente se necesita hacer una copia, como crear una lista con las teclas del diccionario.

El objeto de view tiene lo mejor de ambos mundos: se comporta como un contenedor y, sin embargo, no hace una copia del diccionario. De hecho, es una especie de contenedor virtual de solo lectura que funciona al vincular al diccionario subyacente. No sé si se ve en cualquier otro lugar del Python estándar.

Editar:

@AntonyHatchkins: la razón por la que no devuelve una función de generador es que no permitiría un funcionamiento rápido. Sí, in trabajos para funciones de generador (cuando los llama). Es decir, puedes hacer esto:

def f(): for i in range(10): yield i 5 in f() # True

Pero de acuerdo con la definición de in , si el lado derecho es un generador, python pasará por todos los n elementos del generador, lo que lleva a O(n) complejidad de tiempo. No hay nada que puedas hacer al respecto porque ese es el único comportamiento significativo que es un generador arbitrario.

Por otro lado, en el caso de la vista de diccionario, puede implementarlo in manera que quiera, porque sabe más acerca de los datos que administra. Y, de hecho, in se implementa con O(1) complejidad utilizando una tabla hash. Puede verificarlo ejecutando

>>> d = dict(zip(range(50000000), range(50000000))) >>> 49999999 in d True >>> 49999999 in iter(d) # kinda how generator function would work True >>>

y darse cuenta de lo rápido que se compara la primera entrada con la segunda entrada