Ответ 1
В Python 2.x, range
возвращает список, но в Python 3.x range
возвращает неизменяемую последовательность типа range
.
Python 2.x:
>>> type(range(10))
<type 'list'>
>>> type(xrange(10))
<type 'xrange'>
Python 3.x:
>>> type(range(10))
<class 'range'>
В Python 2.x, если вы хотите получить итерируемый объект, например, в Python 3.x, вы можете использовать функцию xrange
, которая возвращает неизменяемая последовательность типов xrange
.
Преимущество xrange
над range
в Python 2.x:
Преимущество
xrange()
надrange()
минимально (посколькуxrange()
все равно должен создавать значения, когда их спрашивают), за исключением случаев, когда очень сильно используется диапазон на машине с голодающей памятью или когда все элементы диапазона никогда не используются (например, когда цикл обычно заканчивается разрывом).
Примечание:
Кроме того, единственным очевидным способом доступа к целым, созданным
range()
, является их повторение,
Неа. Поскольку объекты range
в Python 3 являются неизменяемыми последовательностями, они также поддерживают индексирование. Цитируя из документации по функциям range
,
Диапазоны реализуют все общие операции последовательности, кроме конкатенации и повторения
...
Объекты Range реализуют
collections.abc.Sequence
ABC и предоставляют такие функции, как тесты сдерживания, поиск индекса элемента, нарезка и поддержка отрицательных индексы.
Например,
>>> range(10, 20)[5]
15
>>> range(10, 20)[2:5]
range(12, 15)
>>> list(range(10, 20)[2:5])
[12, 13, 14]
>>> list(range(10, 20, 2))
[10, 12, 14, 16, 18]
>>> 18 in range(10, 20)
True
>>> 100 in range(10, 20)
False
Все это возможно с этой неизменной последовательностью range
.
Недавно у меня возникла проблема, и я думаю, было бы уместно включить сюда. Рассмотрим этот код Python 3.x
from itertools import islice
numbers = range(100)
items = list(islice(numbers, 10))
while items:
items = list(islice(numbers, 10))
print(items)
Можно было бы ожидать, что этот код будет печатать каждые десять чисел в виде списка до 99. Но он будет работать бесконечно. Можете ли вы объяснить почему?
Решение
Поскольку
range
возвращает неизменяемую последовательность, а не объект итератора. Итак, всякий раз, когдаislice
выполняется на объектеrange
, он всегда начинается с начала. Подумайте об этом как о замене для неизменного списка. Теперь встает вопрос, как вы это исправите? Просто, вы просто должны получить из него итератор. Просто измените
numbers = range(100)
для изображения
numbers = iter(range(100))
Теперьnumbers
является объектом итератора, и он помнит, как долго он был итерирован раньше. Таким образом, когдаislice
выполняет итерацию, он начинается только с того места, где он раньше заканчивался.