python - pyplot - plt ylim
¿Por qué xrange puede volver a comenzar en Python? (3)
Debido a que el objeto xrange
producido al llamar a xrange()
especifica un __iter__
que proporciona una versión única de sí mismo (en realidad, un objeto de rangeiterator
separado) cada vez que se itera.
>>> x = xrange(3)
>>> type(x)
<type ''xrange''>
>>> i = x.__iter__()
>>> type(i)
<type ''rangeiterator''>
Me he encontrado con este código de la forma más pitón de contar elementos coincidentes en algo iterable
r = xrange(1, 10)
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 3
r se itera una vez. y luego se itera de nuevo. Pensé que si un iterador se consume una vez, se termina y no debe repetirse nuevamente.
Las expresiones del generador se pueden iterar solo una vez:
r = (7 * i for i in xrange(1, 10))
print sum(1 for v in r if v % 2 == 0) # 4
print sum(1 for v in r if v % 3 == 0) # 0
enumerar (L) también:
r = enumerate(mylist)
y objeto de archivo también:
f = open(myfilename, ''r'')
¿Por qué xrange se comporta de manera diferente?
Porque xrange
no devuelve un generador. Devuelve un objeto xrange .
>>> type(xrange(10))
<type ''xrange''>
Además de repetidas iteraciones, los objetos xrange
admiten otras cosas que los generadores no admiten, como la indexación:
>>> xrange(10)[5]
5
También tienen una longitud:
>>> len(xrange(10))
10
Y se pueden revertir:
>>> list(reversed(xrange(10)))
[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
En resumen, los objetos xrange
implementan la interface sequence completa:
>>> import collections
>>> isinstance(xrange(10), collections.Sequence)
True
Simplemente lo hacen sin gastar mucha memoria.
Tenga en cuenta también que en Python 3, el objeto de range
devuelto por range
tiene todas las mismas propiedades.
Si todo lo que sabes sobre algo es que es un iterador, en general debes asumir que solo puedes iterar una vez. Eso no significa que cada iterador solo pueda consumirse una vez, solo que cada iterador puede consumirse al menos una vez. El ejemplo obvio es que las listas y otras secuencias admiten esta interfaz.
Como explicaron Senderle y Amber, los iteradores en particular que obtienes al llamar a xrange
se implementan de tal manera que puedes iterar sobre ellos varias veces.
La idea general del iterador permite que los iteradores se agoten después de ser iterados. Esto se debe a que muchos iteradores (como los generadores, el recorrido de archivos, etc.) serían difíciles de implementar, o consumirían mucha más memoria o correrían mucho más lento si tuvieran que soportar arbitrariamente muchos recorridos, y muy a menudo esta funcionalidad no sería usado. Entonces, si los iteradores tuvieran que soportar arbitrariamente muchos recorridos, entonces estas cosas probablemente no serían iteradores.
En pocas palabras, si escribe un código que opera en un iterador desconocido arbitrario, asumirá que solo se puede recorrer una vez, y no importa si alguien le da un objeto que admita más que la funcionalidad que necesita. Si conoce alguna información adicional sobre el iterador (como que también es una secuencia, o incluso que es un objeto de rango extraño), puede codificar para usar eso si lo desea.