2010-09-24 7 views
18

¿Qué son exactamente las vistas en Python3.1? Parecen comportarse de manera similar a la de los iteradores y también se pueden materializar en listas. ¿Cómo son diferentes los iteradores y las vistas?Vistas en Python3.1?

Respuesta

12

Por lo que puedo decir, todavía se adjunta una vista al objeto desde el que se creó. Las modificaciones al objeto original afectan la vista.

del docs (por vistas del diccionario):

>>> dishes = {'eggs': 2, 'sausage': 1, 'bacon': 1, 'spam': 500} 
>>> keys = dishes.keys() 
>>> values = dishes.values() 

>>> # iteration 
>>> n = 0 
>>> for val in values: 
...  n += val 
>>> print(n) 
504 

>>> # keys and values are iterated over in the same order 
>>> list(keys) 
['eggs', 'bacon', 'sausage', 'spam'] 
>>> list(values) 
[2, 1, 1, 500] 

>>> # view objects are dynamic and reflect dict changes 
>>> del dishes['eggs'] 
>>> del dishes['sausage'] 
>>> list(keys) 
['spam', 'bacon'] 

>>> # set operations 
>>> keys & {'eggs', 'bacon', 'salad'} 
{'bacon'} 
5

Yo recomendaría que lea this. Parece hacer el mejor trabajo de explicar.

Por lo que puedo decir, las vistas parecen estar asociadas más a dict sy pueden forzarse a list s. También se puede hacer un iterador de ellos, a través del cual usted podría entonces iterar (en un bucle for o llamando next)

Actualización: updated link from wayback machine

+0

El enlace está muerto. –

+1

@AnirudhRamanathan: He actualizado el enlace. Gracias por hacérmelo saber – inspectorG4dget

1

¿Cómo son los iteradores y puntos de vista diferentes?

voy a reformular la pregunta "¿cuál es la diferencia entre un iterables objetos y un iterador "?

Un iterable es un objeto que puede repetirse (por ejemplo, utilizado en un bucle for).

Un iterador es un objeto que se puede llamar con la función next(), es decir que implementa el método .next() en python2 y .__next__() en python3. Un iterador se usa a menudo para ajustar un iterable y devolver cada elemento de interés. Todos los iteradores son iterables, pero el reverso no es necesariamente cierto (todos los iterables no son iteradores).

Las vistas son objetos iterables, no iteradores.

Veamos algo de código para ver la diferencia (Python 3):

El documento "What's new in Python 3" es muy específico sobre el cual las funciones devuelven iteradores. map(), filter(), y zip() devuelven definitivamente un iterador, mientras que dict.items(), dict.values(), dict.keys() se dice que devuelven un objeto de vista. En cuanto al range(), aunque la descripción de lo que devuelve carece exactamente de precisión, sabemos que no es un iterador.

Usando map() de duplicar todos los números en una lista

m = map(lambda x: x*2, [0,1,2]) 
hasattr(m, '__next__') 
# True 
next(m) 
# 0 
next(m) 
# 2 
next(m) 
# 4 
next(m) 
# StopIteration ... 

Usando filter() para extraer todos los números impares

f = filter(lambda x: x%2==1, [0,1,2,3,4,5,6]) 
hasattr(f, '__next__') 
# True 
next(f) 
# 1 
next(f) 
# 3 
next(f) 
# 5 
next(f) 
# StopIteration ... 

Tratar de utilizar range() de la misma manera para producir una secuencia de número

r = range(3) 
hasattr(r, '__next__') 
# False 
next(r) 
# TypeError: 'range' object is not an iterator 

Pero es ' s un iterable, por lo que debemos ser capaces de envolverlo con un iterador

it = iter(r) 
next(it) 
# 0 
next(it) 
# 1 
next(it) 
# 2 
next(it) 
# StopIteration ... 

dict.items(), así como dict.keys() y dict.values() también no regresan iteradores en Python 3

d = {'a': 0, 'b': 1, 'c': 2} 
items = d.items() 
hasattr(items, '__next__') 
# False 
it = iter(items) 
next(it) 
# ('b', 1) 
next(it) 
# ('c', 2) 
next(it) 
# ('a', 0) 

Un iterador sólo se puede utilizar en un solo bucle for, mientras que un iterable se puede usar repetidamente en los siguientes bucles for. Cada vez que se utiliza un iterable en este contexto, devuelve implícitamente un nuevo iterador (desde su método __iter__()). La siguiente clase personalizada demuestra esto mediante la salida de la memoria id tanto del objeto de lista y el objeto iterador de regresar:

class mylist(list): 
    def __iter__(self, *a, **kw): 
     print('id of iterable is still:', id(self)) 
     rv = super().__iter__(*a, **kw) 
     print('id of iterator is now:', id(rv)) 
     return rv 

l = mylist('abc') 

Un bucle for puede utilizar el objeto iterable y tendrá implícitamente obtener un iterador

for c in l: 
    print(c) 
# id of iterable is still: 139696242511768 
# id of iterator is now: 139696242308880 
# a 
# b 
# c 

Un siguiente ciclo for puede usar el mismo objeto iterable, pero obtendrá otro iterador

for c in l: 
    print(c) 
# id of iterable is still: 139696242511768 
# id of iterator is now: 139696242445616 
# a 
# b 
# c 

También podemos obtener un iterador explícitamente

it = iter(l) 
# id of iterable is still: 139696242511768 
# id of iterator is now: 139696242463688 

pero sólo entonces podemos ser usado una vez

for c in it: 
    print(c) 
# a 
# b 
# c 
for c in it: 
    print(c) 
for c in it: 
    print(c) 
Cuestiones relacionadas