Почему или почему нет?Должны ли вы всегда поддерживать xrange() над диапазоном()?
ответ
Для исполнения, особенно при повторении в большом диапазоне, обычно лучше xrange()
. Тем не менее, есть еще несколько случаев, почему вы предпочтете range()
:
В Python 3,
range()
делает то, чтоxrange()
используется, чтобы сделать иxrange()
не существует. Если вы хотите написать код, который будет работать как на Python 2, так и на Python 3, вы не сможете использоватьxrange()
.range()
может быть в некоторых случаях быстрее, например. если итерация по одной и той же последовательности несколько раз.xrange()
должен каждый раз восстанавливать целочисленный объект, ноrange()
будет иметь действительные целые объекты. (Однако он будет всегда хуже работать с точки зрения памяти)xrange()
не может использоваться в любых случаях, когда необходим реальный список. Например, он не поддерживает срезы или любые методы списка.
[изменить] Есть несколько сообщений с упоминанием как range()
будет модернизирован с помощью инструмента 2to3. Для записи, вот выход запуска средства на некоторые примеры использований range()
и xrange()
RefactoringTool: Skipping implicit fixer: buffer
RefactoringTool: Skipping implicit fixer: idioms
RefactoringTool: Skipping implicit fixer: ws_comma
--- range_test.py (original)
+++ range_test.py (refactored)
@@ -1,7 +1,7 @@
for x in range(20):
- a=range(20)
+ a=list(range(20))
b=list(range(20))
c=[x for x in range(20)]
d=(x for x in range(20))
- e=xrange(20)
+ e=range(20)
Как вы можете видеть, когда он используется в цикле или понимания, или там, где уже завернутые со списком(), диапазон остается неизменным.
xrange()
более эффективен, потому что вместо генерации списка объектов он генерирует только один объект за раз. Вместо 100 целых чисел и всех их накладных расходов, а также списка для их ввода, у вас есть только одно целое за раз. Более быстрое поколение, лучшее использование памяти, более эффективный код.
Если я специально не нужен список чего-то, я всегда благоприятствуют xrange()
Вы должны благоприятствовать range()
над xrange()
только тогда, когда вам нужен фактический список. Например, если вы хотите изменить список, возвращенный range()
, или когда вы хотите его отрезать. Для итерации или даже просто нормального индексации xrange()
будет работать нормально (и обычно намного эффективнее). Есть точка, в которой range()
немного быстрее, чем xrange()
для очень маленьких списков, но в зависимости от вашего оборудования и различных других деталей безубыточность может быть в результате длины 1 или 2; не о чем беспокоиться. Предпочитает xrange()
.
Берите с диапазоном по этим причинам:
1) xrange будет уходить в более новых версиях Python. Это дает вам легкую совместимость в будущем.
2) диапазон будет принимать на себя эффективность, связанную с xrange.
Не делайте этого. xrange() исчезнет, но так будет и многое другое. Инструмент, который вы будете использовать для перевода кода Python 2.x в код Python 3.x, автоматически преобразует xrange() в range(), но range() будет переведен в менее эффективный список (range()). – 2008-09-25 19:14:44
range() возвращает список, xrange() возвращает объект xrange.
xrange() работает немного быстрее и немного более эффективно. Но выигрыш не очень большой.
Дополнительная память, используемая списком, конечно, не просто пуста, списки имеют больше функциональности (фрагмент, повтор, вставка, ...). Точные различия можно найти в documentation. Нет правила костей, используйте то, что нужно.
Python 3.0 все еще находится в разработке, но диапазон IIRC() будет очень похож на xrange() of 2.X, а list (range()) можно использовать для создания списков.
Хорошо, все здесь, как другое мнение относительно компромиссов и преимуществ xrange versus range. Они в основном правильны, xrange - это итератор, а также диапазон fleshes и создает фактический список. В большинстве случаев вы не заметите разницы между ними. (Вы можете использовать карту с диапазоном, но не с xrange, но она использует больше памяти.)
Однако, я думаю, вы хотите услышать, что предпочтительным выбором является xrange. Поскольку диапазон в Python 3 является итератором, инструмент преобразования кода 2to3 будет правильно преобразовывать все применения xrange в диапазон и выкинет ошибку или предупреждение для использования диапазона. Если вы хотите, чтобы в будущем вы легко конвертировали свой код, вы будете использовать только xrange и список (xrange), если вы уверены, что хотите получить список. Я узнал об этом во время спринта CPython в PyCon в этом году (2008) в Чикаго.
Нет, они оба имеют свою область применения:
Использование xrange()
при переборе, как это экономит память. Скажи:
for x in xrange(1, one_zillion):
вместо:
for x in range(1, one_zillion):
С другой стороны, использовать range()
, если вы на самом деле хотите получить список номеров.
multiples_of_seven = range(7,100,7)
print "Multiples of seven < 100: ", multiples_of_seven
Я хотел бы просто сказать, что это ДЕЙСТВИТЕЛЬНО не так сложно получить объект xrange с функцией среза и индексирования. Я написал код, который хорошо работает, и так же быстро, как xrange, когда он подсчитывает (итерации).
from __future__ import division
def read_xrange(xrange_object):
# returns the xrange object's start, stop, and step
start = xrange_object[0]
if len(xrange_object) > 1:
step = xrange_object[1] - xrange_object[0]
else:
step = 1
stop = xrange_object[-1] + step
return start, stop, step
class Xrange(object):
''' creates an xrange-like object that supports slicing and indexing.
ex: a = Xrange(20)
a.index(10)
will work
Also a[:5]
will return another Xrange object with the specified attributes
Also allows for the conversion from an existing xrange object
'''
def __init__(self, *inputs):
# allow inputs of xrange objects
if len(inputs) == 1:
test, = inputs
if type(test) == xrange:
self.xrange = test
self.start, self.stop, self.step = read_xrange(test)
return
# or create one from start, stop, step
self.start, self.step = 0, None
if len(inputs) == 1:
self.stop, = inputs
elif len(inputs) == 2:
self.start, self.stop = inputs
elif len(inputs) == 3:
self.start, self.stop, self.step = inputs
else:
raise ValueError(inputs)
self.xrange = xrange(self.start, self.stop, self.step)
def __iter__(self):
return iter(self.xrange)
def __getitem__(self, item):
if type(item) is int:
if item < 0:
item += len(self)
return self.xrange[item]
if type(item) is slice:
# get the indexes, and then convert to the number
start, stop, step = item.start, item.stop, item.step
start = start if start != None else 0 # convert start = None to start = 0
if start < 0:
start += start
start = self[start]
if start < 0: raise IndexError(item)
step = (self.step if self.step != None else 1) * (step if step != None else 1)
stop = stop if stop is not None else self.xrange[-1]
if stop < 0:
stop += stop
stop = self[stop]
stop = stop
if stop > self.stop:
raise IndexError
if start < self.start:
raise IndexError
return Xrange(start, stop, step)
def index(self, value):
error = ValueError('object.index({0}): {0} not in object'.format(value))
index = (value - self.start)/self.step
if index % 1 != 0:
raise error
index = int(index)
try:
self.xrange[index]
except (IndexError, TypeError):
raise error
return index
def __len__(self):
return len(self.xrange)
Честно говоря, я думаю, что вся проблема отчасти глупо и xrange должны делать все это так или иначе ...
Еще одно различие в том, что xrange() не может поддерживать число больше, чем Интс C , поэтому, если вы хотите иметь диапазон, используя встроенную поддержку большого числа python, вам нужно использовать range().
Python 2.7.3 (default, Jul 13 2012, 22:29:01)
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
[123456787676676767676676L, 123456787676676767676677L, 123456787676676767676678L]
>>> xrange(123456787676676767676676,123456787676676767676679)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OverflowError: Python int too large to convert to C long
Python 3 не имеет этой проблемы:
Python 3.2.3 (default, Jul 14 2012, 01:01:48)
[GCC 4.7.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> range(123456787676676767676676,123456787676676767676679)
range(123456787676676767676676, 123456787676676767676679)
Хороший пример приведен в книге: Practical Python Магнусом Ли Хетланд
>>> zip(range(5), xrange(100000000))
[(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
Я бы не рекомендовал использовать диапазон вместо xrange в предыдущем примере - хотя нужны только первые пять чисел, диапазон вычисляет все числа, и это может занять много времени. С xrange это не проблема, потому что он вычисляет только те числа, которые необходимы.
Да, я прочитал ответ Брайана: В python 3, range() все равно является генератором, а xrange() не существует.
range()
:range(1, 10)
возвращает список от 1 до 10 номеров & держать весь список в памяти.xrange()
: Как иrange()
, но вместо того, чтобы возвращать список, возвращает объект, который генерирует числа в диапазоне по запросу. Для циклирования это намного быстрее, чемrange()
и более эффективен с точки зрения памяти.xrange()
объект как итератор и генерирует числа по требованию (ленивая оценка).
In [1]: range(1,10)
Out[1]: [1, 2, 3, 4, 5, 6, 7, 8, 9]
In [2]: xrange(10)
Out[2]: xrange(10)
In [3]: print xrange.__doc__
Out[3]: xrange([start,] stop[, step]) -> xrange object
range()
делает то же самое, как xrange()
используется, чтобы сделать в Python 3 и там не срок xrange()
существует в Python 3. range()
может быть на самом деле быстрее, в каком-то случае, если вы итерация то же самое последовательность несколько раз. xrange()
должен каждый раз восстанавливать целочисленный объект, но range()
будет иметь действительные целые объекты.
В то время как xrange
быстрее, чем range
, в большинстве случаев разница в производительности довольно минимальна. Немного ниже программа сравнивает Перебор range
и xrange
:
import timeit
# Try various list sizes.
for list_len in [1, 10, 100, 1000, 10000, 100000, 1000000]:
# Time doing a range and an xrange.
rtime = timeit.timeit('a=0;\nfor n in range(%d): a += n'%list_len, number=1000)
xrtime = timeit.timeit('a=0;\nfor n in xrange(%d): a += n'%list_len, number=1000)
# Print the result
print "Loop list of len %d: range=%.4f, xrange=%.4f"%(list_len, rtime, xrtime)
Приведенные ниже результаты показывают, что xrange
действительно быстрее, но не достаточно, чтобы попотеть.
Loop list of len 1: range=0.0003, xrange=0.0003
Loop list of len 10: range=0.0013, xrange=0.0011
Loop list of len 100: range=0.0068, xrange=0.0034
Loop list of len 1000: range=0.0609, xrange=0.0438
Loop list of len 10000: range=0.5527, xrange=0.5266
Loop list of len 100000: range=10.1666, xrange=7.8481
Loop list of len 1000000: range=168.3425, xrange=155.8719
Так все средства использовать xrange
, но если вы не находитесь на ограниченное оборудовании, не слишком беспокоиться об этом.
- 1. Должны ли мы поддерживать контроль над метаданными подключения
- 2. Должны ли вы только издеваться над своими типами?
- 3. Должны ли вы всегда ожидать проблемы, вызванные параметризацией?
- 4. Должны ли вы всегда заканчивать mysql-запросы «или умирать?»
- 5. Должны ли вы всегда кодировать интерфейсы в Java
- 6. XNA/DirectX: Должны ли вы всегда использовать индексы?
- 7. Должны ли вы всегда компилироваться с новой версией библиотеки?
- 8. Должны ли хранилища управления версиями поддерживать поиск?
- 9. Какая самая неудобная программа, которую вы должны были поддерживать?
- 10. Должны ли всегда пытаться поймать?
- 11. Excel sumif над несмежным диапазоном
- 12. Должны ли подразумеваемые классы всегда расширять AnyVal?
- 13. Meteor.js - Должны ли вы денормализовать данные?
- 14. Импорт. Должны ли вы, не должны ли вы, синтаксис и рекомендации?
- 15. Должны ли вы утилизировать объекты jQuery?
- 16. Должны ли обработчики NServiceBus всегда быстро завершаться?
- 17. Должны ли объекты домена всегда загружаться полностью?
- 18. vba Loop над несмежным диапазоном
- 19. Должны ли издеваться над предметными событиями?
- 20. Что вы должны учитывать при выполнении операций над двусвязными списками?
- 21. Когда вы должны начать использовать замену строки над sprintf?
- 22. Как всегда поддерживать приложение web.py?
- 23. Должны ли быть сделаны защитные копии ВСЕГДА?
- 24. Должны ли конструкторы всегда быть публичными?
- 25. Должны ли структуры всегда быть неизменными?
- 26. Должны ли sprocs (всегда) возвращать полный объект?
- 27. Должны ли мы всегда переопределять равные?
- 28. Что вы должны сделать, чтобы настроить операции над пользовательскими объектами?
- 29. Что вы должны использовать сопрограммы над функциями в Python?
- 30. Вы должны ToList()?
Может ли кто-нибудь кратко описать разницу между двумя парнями, не являющимися питонами, для нас? Возможно, что-то вроде «xrange() делает каждый диапазон range(), но также поддерживает X, Y и Z». – 2008-09-25 20:45:57
range (n) создает список, содержащий все целые числа 0..n-1. Это проблема, если вы используете диапазон (1000000), потому что в итоге вы получите список> 4Mb. xrange связывается с этим, возвращая объект, который претендует на роль списка, но просто вычисляет число, необходимое из запрошенного индекса, и возвращает это. – Brian 2008-09-25 21:08:08
См. Http://stackoverflow.com/questions/94935/ – 2012-04-13 18:48:00