Недавно я начал использовать 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 был удален? Это такой отличный инструмент для изучения. Для начинающих, как и я, как и все мы были в какой-то момент. Зачем удалять это? Может кто-нибудь указать мне на правильный ПКП, я не могу его найти.
Приветствия.
python
python-3.x
pep
xrange
catalesia
источник
источник
range
в Python 3.x взятxrange
из Python 2.x. Это был фактически Python 2.x,range
который был удален.time
. Помимо того, что его проще использовать и труднее ошибиться, а также повторять для вас тесты, онtimeit
заботится обо всех вещах, о которых вы не помните или даже не знаете, как позаботиться (например, об отключении GC), и может использовать часы с разрешением в тысячи раз лучше.range
наx%4 == 0
? Почему бы не просто проверитьlist(xrange())
противlist(range())
, так что , как мало посторонней работы , как это возможно? (Например, как вы узнаете, что 3.x не работаетx%4
медленнее?) В этом отношении, почему вы строите огромныйlist
, который включает в себя большое выделение памяти (который, помимо того, что он медленный, также невероятно изменчив)? ?iter(range)
избыточноlist(range(..))
. Это эквивалентно диапазону Python 2. Или сказать по-другому: xrange был переименован в range, потому что он лучше по умолчанию; не было необходимости иметь оба, делайте,list(range)
если вам действительно нужен список. ,Ответы:
Некоторые измерения производительности, используя
timeit
вместо того, чтобы пытаться сделать это вручнуюtime
.Во-первых, Apple 2.7.2 64-битная:
Теперь python.org 3.3.0 64-bit:
По- видимому, 3.x
range
действительно немного медленнее , чем 2.xxrange
. Иxrange
функция ОП не имеет к этому никакого отношения. (Не удивительно, поскольку одноразовый вызов в__iter__
слот вряд ли будет виден среди 10000000 вызовов, что бы ни происходило в цикле, но кто-то поднял это как возможность.)Но это только на 30% медленнее. Как ОП получил 2x как медленный? Что ж, если я повторю те же тесты с 32-битным Python, я получу 1,58 против 3,12. Поэтому я предполагаю, что это еще один из тех случаев, когда 3.x был оптимизирован для 64-битной производительности таким образом, что это наносит ущерб 32-битной системе.
Но действительно ли это имеет значение? Проверьте это, с 3.3.0 64-битными снова:
Таким образом, сборка
list
занимает более чем вдвое больше времени, чем вся итерация.А что касается «потребляет гораздо больше ресурсов, чем Python 2.6+», то из моих тестов похоже, что 3.x
range
точно такого же размера, что и 2.xxrange
- и, даже если он в 10 раз больше, создает ненужный список все еще на 10000000 раз больше проблем, чем любая другая итерация диапазона.А как насчет явного
for
цикла вместо цикла C внутриdeque
?Таким образом, на
for
утверждение тратится почти столько же времени, сколько и на реальную работу по итерацииrange
.Если вы беспокоитесь об оптимизации итерации объекта диапазона, вы, вероятно, смотрите не в том месте.
Между тем вы продолжаете спрашивать, почему
xrange
был удален, независимо от того, сколько раз люди говорили вам одно и то же, но я повторю это еще раз: он не был удален: он был переименованrange
, а 2.xrange
- это то, что было удалено.Вот некоторые доказательства того, что
range
объект 3.3 является прямым потомкомxrange
объекта 2.x (а неrange
функции 2.x ): источник 3.3range
и 2.7xrange
. Вы даже можете увидеть историю изменений (я думаю, что она связана с изменением, которое заменило последний экземпляр строки «xrange» в любом месте файла).Итак, почему это медленнее?
Ну, например, они добавили много новых функций. С другой стороны, они сделали все виды изменений повсеместно (особенно внутри итерации), которые имеют незначительные побочные эффекты. И было проделано много работы, чтобы значительно оптимизировать различные важные случаи, даже если иногда они слегка пессимизируют менее важные случаи. Добавьте все это, и я не удивлен, что итерация
range
как можно быстрее теперь немного медленнее. Это один из тех менее важных случаев, на которых никто никогда не будет обращать внимания. Ни у кого, вероятно, никогда не будет реального сценария использования, где эта разница в производительности является горячей точкой в их коде.источник
range
.range
Объект в 3.3 является прямым потомкомxrange
объекта в 2.7, а не изrange
функции в 2.7. Это все равно что спросить, покаitertools.imap
убрали в пользуmap
. Ответа нет, потому что такого не было.range
, не делая ничего другого.Диапазон Python3 в это xrange python2 в. Там нет необходимости обернуть его вокруг него. Чтобы получить актуальный список в Python3, вам нужно использовать
list(range(...))
Если вы хотите что-то, что работает с Python2 и Python3, попробуйте это
источник
range
иxrange
будет вести себя по-разному. Этого недостаточно, нужно также убедиться, что вы никогда не предполагаете, чтоrange
это возвращает список (как это было бы в python 2).futurize
инструмент для автоматического преобразования исходного кода: python-future.org/…range
Тип Python 3 работает так же, как Python 2xrange
. Я не уверен, почему вы видите замедление, поскольку итератор, возвращаемый вашейxrange
функцией, - это именно то, что вы получите, если бы итерировалиrange
напрямую.Я не могу воспроизвести замедление в моей системе. Вот как я тестировал:
Python 2, с
xrange
:Python 3 с
range
немного быстрее:Недавно я узнал, что
range
тип Python 3 имеет некоторые другие полезные функции, такие как поддержка нарезки:range(10,100,2)[5:25:5]
естьrange(20, 60, 10)
!источник
xrange
столько раз, или это происходит только один раз?xrange
это не было удалено, просто переименовано .range
Насколько мне известно, самая большая победа в 3.x - это постоянное время__contains__
. Новички обычно писали,300000 in xrange(1000000)
и это заставляло его перебирать целоеxrange
(или, по крайней мере, первые 30%), поэтому нам пришлось объяснить, почему это была плохая идея, даже если она выглядит такой питонической. Теперь, это вещий.Один из способов исправить код на python2:
источник
range = xrange
как есть в комментарии @John La Royxrange = range
... я сменил заявленияxrange из Python 2 является генератором и реализует итератор, а range - просто функцией. В Python3 я не знаю, почему выпал Xrange.
источник
range()
является эквивалентом PY2xrange()
. И, таким образом, в PY3xrange()
является избыточным.comp: ~ $ python Python 2.7.6 (по умолчанию, 22 июня 2015 г., 17:58:13) [GCC 4.8.2] в linux2
+5,656799077987671
+5,579368829727173
+21,54827117919922
+22,014557123184204
С номером time = 1 параметр:
0,2245171070098877
+0,10750913619995117
comp: ~ $ python3 Python 3.4.3 (по умолчанию, 14 октября 2015 г., 20:28:29) [GCC 4.8.4] в Linux
+9,113872020003328
+9,07014398300089
С timeit number = 1,2,3,4 param работает быстро и линейно:
+0,09329321900440846
+0,18501482300052885
0,2703447980020428
+0,36209142999723554
Поэтому кажется, что если мы измерим 1 цикл работающего цикла, например timeit.timeit («[x для x в диапазоне (1000000), если x% 4]», число = 1) (как мы фактически используем в реальном коде), python3 работает достаточно быстро, но в повторяющихся циклах python 2 xrange () выигрывает в скорости против range () у python 3.
источник