Pregunta

  

métodos dict dict.keys (), dict.items ()   y dict.values ??() devuelven & # 8220; vistas & # 8221;   en lugar de listas    http://docs.python.org/dev/3.0/whatsnew//3.0 .html

En primer lugar, ¿en qué se diferencia una vista 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 estoy recuperando algo más. ¿Esto confundirá a la gente?

¿Fue útil?

Solución

Está efectivamente 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.

Esa es la misma forma en que se implementa en Java (y probablemente también 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. Se requeriría copiar todo el contenido (que puede o no ser mucho).

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

Otros consejos

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, tal como lo hicieron 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, encontrará 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 verifica si un elemento está " en " el iterador, el iterador se destruye!

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

El objeto 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 mediante la vinculación al diccionario subyacente. No sé si se ha visto en otro lugar en el Python estándar.

Editar:

@AntonyHatchkins: la razón por la que no devuelve una función de generador es porque no permitiría una operación rápida de in . Sí, in funciona para las funciones del generador (cuando las llamas). Es decir, puedes hacer esto:

def f():
  for i in range(10):
    yield i

5 in f() # True

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

Por otro lado, en el caso de la vista de diccionario, puede implementar en de la forma que desee, porque sabe más sobre los datos que administra. Y, de hecho, in se implementa con la complejidad O (1) 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 observando qué tan rápido se compara el primer en con el segundo en .

Como ya se mencionó en la pregunta relacionada, la vista tiene el método len () , del que carece el iterador (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 membresía optimizada en operaciones O (1) en lugar de O (N) para la lista (o iterador).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top