not name python python-3.x pep xrange

python - name ''xrange'' is not defined



¿Por qué no hay una función xrange en Python3? (6)

Algunas mediciones de rendimiento, utilizando timeit lugar de intentar hacerlo manualmente con el time .

Primero, Apple 2.7.2 de 64 bits:

In [37]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.05 s per loop

Ahora, python.org 3.3.0 64-bit:

In [83]: %timeit collections.deque((x for x in range(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.32 s per loop In [84]: %timeit collections.deque((x for x in xrange(10000000) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.31 s per loop In [85]: %timeit collections.deque((x for x in iter(range(10000000)) if x%4 == 0), maxlen=0) 1 loops, best of 3: 1.33 s per loop

Al parecer, el range 3.x es un poco más lento que el xrange 2.x. Y la función xrange del OP no tiene nada que ver con eso. (No es sorprendente, ya que una llamada de una sola vez a la ranura __iter__ no es probable que sea visible entre 10000000 llamadas a lo que suceda en el bucle, pero alguien lo mencionó como una posibilidad).

Pero es solo un 30% más lento. ¿Cómo el OP consiguió 2x tan lento? Bueno, si repito las mismas pruebas con Python de 32 bits, obtengo 1.58 frente a 3.12. Entonces, supongo que este es otro de esos casos en los que 3.x se ha optimizado para un rendimiento de 64 bits de manera que daña a 32 bits.

pero, realmente importa? Mira esto, con 3.3.0 64 bits de nuevo:

In [86]: %timeit [x for x in range(10000000) if x%4 == 0] 1 loops, best of 3: 3.65 s per loop

Por lo tanto, la creación de la list lleva más del doble que toda la iteración.

Y en cuanto a "consume muchos más recursos que Python 2.6+", según mis pruebas, parece que un range 3.x es exactamente del mismo tamaño que un xrange 2.x, y, aunque fuera 10 veces más grande, la construcción de La lista innecesaria sigue siendo aproximadamente 10000000x más de un problema que cualquier otra cosa que pueda hacer la iteración del rango.

¿Y qué hay de un bucle for explícito for lugar del bucle C dentro de deque ?

In [87]: def consume(x): ....: for i in x: ....: pass In [88]: %timeit consume(x for x in range(10000000) if x%4 == 0) 1 loops, best of 3: 1.85 s per loop

Entonces, casi tanto tiempo perdido en la declaración for como en el trabajo real de iterar el range .

Si le preocupa optimizar la iteración de un objeto de rango, probablemente esté buscando en el lugar equivocado.

Mientras tanto, sigue preguntando por xrange se eliminó xrange , sin importar cuántas veces la gente te diga lo mismo, pero lo repetiré nuevamente: no se eliminó: se cambió su nombre a range , y el range 2.x es lo que era remoto.

Aquí hay algunas pruebas de que el objeto de range 3.3 es un descendiente directo del objeto xrange 2.x (y no de la función de range 2.x): la fuente del range 3.3 y del range 2.7 . Incluso puede ver el historial de cambios (vinculado, creo, el cambio que reemplazó la última instancia de la cadena "xrange" en cualquier parte del archivo).

Entonces, ¿por qué es más lento?

Bueno, por un lado, han agregado muchas características nuevas. Por otro lado, han realizado todo tipo de cambios en todo el lugar (especialmente dentro de la iteración) que tienen efectos secundarios menores. Y había habido mucho trabajo para optimizar dramáticamente varios casos importantes, incluso si a veces pesimiza ligeramente los casos menos importantes. Sume todo esto y no me sorprende que iterar un range más rápido posible ahora sea un poco más lento. Es uno de esos casos menos importantes que a nadie le importaría lo suficiente como para centrarse. Es probable que nadie tenga un caso de uso en la vida real en el que esta diferencia de rendimiento sea el hotspot en su código.

Recientemente comencé a usar Python3 y es la falta de heridas de rango extraño.

Ejemplo simple:

1) Python2:

from time import time as t def count(): st = t() [x for x in xrange(10000000) if x%4 == 0] et = t() print et-st count()

2) Python3:

from time import time as t def xrange(x): return iter(range(x)) def count(): st = t() [x for x in xrange(10000000) if x%4 == 0] et = t() print (et-st) count()

Los resultados son, respectivamente:

1) 1.53888392448 2) 3.215819835662842

¿Porqué es eso? Quiero decir, ¿por qué se ha eliminado xrange? Es una gran herramienta para aprender. Para los principiantes, igual que yo, como todos fuimos en algún momento. ¿Por qué quitarlo? Alguien me puede indicar el PEP adecuado, no puedo encontrarlo.

Aclamaciones.


El rango de Python3 es el rango de Python2. No hay necesidad de envolver un iter a su alrededor. Para obtener una lista real en Python3, debe usar la list(range(...))

Si quieres algo que funcione con Python2 y Python3, prueba esto

try: xrange except NameError: xrange = range


El tipo de range Python 3 funciona igual que el range Python 2. No estoy seguro de por qué está viendo una desaceleración, ya que el iterador devuelto por su función xrange es exactamente lo que obtendría si iterara sobre el range directamente.

No puedo reproducir la ralentización de mi sistema. Así es como lo he probado:

Python 2, con xrange :

Python 2.7.3 (default, Apr 10 2012, 23:24:47) [MSC v.1500 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information. >>> import timeit >>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100) 18.631936646865853

Python 3, con range es un poquito más rápido:

Python 3.3.0 (v3.3.0:bd8afb90ebf2, Sep 29 2012, 10:57:17) [MSC v.1600 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information. >>> import timeit >>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100) 17.31399508687869

Hace poco me enteré de que el tipo de range Python 3 tiene otras características interesantes, como la compatibilidad con el corte en rebanadas: el range(10,100,2)[5:25:5] es el range(15, 60, 10) !


Una forma de arreglar tu código python2 es:

import sys if sys.version_info >= (3, 0): def xrange(*args, **kwargs): return iter(range(*args, **kwargs))


xrange de Python 2 es un generador e implementa iterador mientras que range es solo una función. En Python3 no sé por qué se dejó caer el rango.


comp: ~ $ python Python 2.7.6 (predeterminado, 22 de junio de 2015, 17:58:13) [GCC 4.8.2] en linux2

>>> import timeit >>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.656799077987671

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=100)

5.579368829727173

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

21.54827117919922

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

22.014557123184204

Con el número de timeit = 1 param:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.2245171070098877

>>> timeit.timeit("[x for x in xrange(1000000) if x%4]",number=1)

0.10750913619995117

comp: ~ $ python3 Python 3.4.3 (predeterminado, 14 de octubre de 2015, 20:28:29) [GCC 4.8.4] en linux

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.113872020003328

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=100)

9.07014398300089

Con timeit number = 1,2,3,4 param trabaja de forma rápida y lineal:

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=1)

0.09329321900440846

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=2)

0.18501482300052885

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=3)

0.2703447980020428

>>> timeit.timeit("[x for x in range(1000000) if x%4]",number=4)

0.36209142999723554

Así que parece que si medimos 1 ciclo de bucle en ejecución como timeit.timeit ("[x para x en el rango (1000000) si x% 4]", número = 1) (como en realidad usamos en código real) python3 funciona lo suficientemente rápido, pero en ciclos repetidos, python 2 xrange () gana en velocidad contra el rango () de python 3.