Насколько я понимаю, range()
функция, которая на самом деле является типом объекта в Python 3 , генерирует свое содержимое на лету, подобно генератору.
В этом случае я ожидал, что следующая строка займет неоправданное количество времени, потому что для определения того, находится ли 1 квадриллион в этом диапазоне, необходимо сгенерировать квадриллионные значения:
1000000000000000 in range(1000000000000001)
Более того: кажется, что независимо от того, сколько нулей я добавляю, вычисление более или менее занимает одинаковое количество времени (в основном, мгновенное).
Я также пробовал такие вещи, но расчет все еще почти мгновенный:
1000000000000000000000 in range(0,1000000000000000000001,10) # count by tens
Если я попытаюсь реализовать свою собственную функцию диапазона, результат будет не таким хорошим !!
def my_crappy_range(N):
i = 0
while i < N:
yield i
i += 1
return
Что range()
делает объект под капотом, что делает его таким быстрым?
Ответ Martijn Pieters был выбран из-за его полноты, но также см . Первый ответ abarnert для хорошего обсуждения того, что значит range
быть полноценной последовательностью в Python 3, и некоторую информацию / предупреждение относительно потенциальной несогласованности для __contains__
оптимизации функций во всех реализациях Python. , Другой ответ abarnert входит в некоторые подробности и предоставляет ссылки для тех, кто интересуется историей, стоящей за оптимизацией в Python 3 (и отсутствием оптимизации xrange
в Python 2). Ответы poke и wim предоставляют соответствующий исходный код на C и объяснения для тех, кто заинтересован.
range
это генератор?
xrange
же, как Python3range
?
xrange()
объектов @Superbest нет __contains__
метода, поэтому проверка элементов должна проходить по всем элементам. Кроме того, есть несколько других изменений range()
, например, он поддерживает нарезку (которая снова возвращает range
объект), а также имеет count
и index
методы для обеспечения его совместимости с collections.Sequence
ABC.
bool
илиlong
типом, с другими типами объектов это сойдет с ума. Попробуйте:100000000000000.0 in range(1000000000000001)