Почему в Python3 нет функции xrange?
недавно я начал использовать Python3, и это отсутствие xrange болит.
простой пример:
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()
результаты, соответственно:
1) 1.53888392448
2) 3.215819835662842
почему это? Я имею в виду, почему xrange был удален? Это такой отличный инструмент для обучения. Для новичков, как и я, как и мы все были в какой-то момент. Зачем его удалять? Может кто-нибудь указать мне на правильный PEP, я не могу его найти.
Ура.
6 ответов:
некоторые измерения производительности, используя
timeitвместо того, чтобы пытаться сделать это вручную сtime.во-первых, Apple 2.7.2 64-бит:
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теперь, python.org 3.3.0 64-разрядная:
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видимо, 3.x
rangeдействительно немного медленнее, чем 2.xxrange. И ОПxrangeфункция не имеет к этому никакого отношения. (Не удивительно, как разовый звонок в__iter__слот вряд ли будет виден среди 10000000 вызовов к тому, что происходит в петля, но кто-то поднял ее как возможность.)но это только на 30% медленнее. Как ОП стал 2x таким медленным? Ну, если я повторю те же тесты с 32-битным Python, я получаю 1.58 против 3.12. Так что я думаю, что это еще один из тех случаев, когда 3.x был оптимизирован для 64-разрядной производительности таким образом, чтобы повредить 32-разрядную.
но разве это имеет значение? Проверьте это, с 3.3.0 64-бит снова:
In [86]: %timeit [x for x in range(10000000) if x%4 == 0] 1 loops, best of 3: 3.65 s per loopИтак, строим
listзанимает более чем в два раза как долго, чем вся итерация.а что касается "потребляет гораздо больше ресурсов, чем Python 2.6+", из моих тестов, это выглядит как 3.x
rangeточно такой же размер, как и 2.xxrange-и, даже если бы он был в 10 раз больше, создание ненужного списка по-прежнему составляет около 10000000x больше проблем, чем все, что может сделать итерация диапазона.а как насчет явного
forцикл вместо цикла C внутри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так, почти столько же времени потрачено впустую в
forзаявление, как в реальной работе итерацииrange.если вы беспокоитесь об оптимизации итерации объекта диапазона, вы, вероятно, ищете не в том месте.
между тем, вы продолжаете спрашивать, почему
xrangeбыл удален, независимо от того, сколько раз люди говорят вам одно и то же, но я повторю это снова: он не был удален: он был переименован вrange, и 2.xrangeчто было удаленный.вот некоторые доказательства того, что 3.3
диапазон Python3 - это вместо python2 по. Там нет необходимости, чтобы обернуть итер вокруг него. Чтобы получить реальный список в Python3, вам нужно использовать
list(range(...))Если вы хотите что-то, что работает с Python2 и Python3, попробуйте это
try: xrange except NameError: xrange = range
Python 3's
rangeтип работает так же, как в Python 2 этоxrange. Я не уверен, почему вы видите замедление, так как итератор, возвращаемыйxrangeфункция-это именно то, что вы получите, если вы повторитеrangeнапрямую.Я не могу воспроизвести замедление в моей системе. Вот как я тестировал:
Python 2, с
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, с
rangeнемного быстрее: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Я недавно узнал что Python 3-х
rangeтип имеет некоторые другие интересные функции, такие как поддержка для нарезки:range(10,100,2)[5:25:5]иrange(15, 60, 10)!
один из способов исправить ваш код python2:
import sys if sys.version_info >= (3, 0): def xrange(*args, **kwargs): return iter(range(*args, **kwargs))
xrange от Python 2 является генератором и реализует итератор, в то время как диапазон-это просто функция. В Python3 я не знаю, почему был сброшен xrange.
comp:~$ python Python 2.7.6 (по умолчанию, 22 июня 2015, 17: 58:13) [GCC 4.8.2] на 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
с номером timeit=1 парам:
>>> 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 (по умолчанию, 14 октября 2015, 20: 28:29) [GCC 4.8.4] на 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
С номером timeit=1,2,3,4 param работает быстро и в линейном образом:
>>> 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
так кажется, если мы измеряем 1 цикл цикла работы, как timeit.timeit ("[x для x в диапазоне (1000000), если x%4]", number=1) (Как мы фактически используем в реальном коде) python3 работает достаточно быстро, но в повторных циклах python 2 xrange () выигрывает в скорости против range () от python 3.
Comments