Почему диапазон не итератор, а обратный (диапазон)? - PullRequest
0 голосов
/ 30 января 2020

Почему я могу звонить рядом с обратным диапазоном, но не могу звонить в обычном диапазоне?

 r1 = range(6)
 next(r1) # Error
 r2 = reversed(range(6))
 next(r2) # -> 5

Ответы [ 2 ]

1 голос
/ 30 января 2020

Здесь есть тонкое различие. Во-первых, range это тип. Экземпляр range не является итератором, поскольку range.__next__ не определен. Экземпляр имеет значение iterable , хотя, поскольку range.__iter__ определен, вы можете получить итератор, например, iter(range(3)).

>>> type(range(1))
<class 'range'>
>>> type(iter(range(1)))
<class 'range_iterator'>

range.__next__ не определен , но range_iterator.__next__ - это.

Экземпляр range представляет ограниченную последовательность целых чисел, фактически не является ограниченной последовательностью. Таким образом, вы можете иметь несколько независимых итераторов в одном и том же диапазоне.

>>> r = range(10)
>>> i1 = iter(r)
>>> next(i1)
0
>>> next(i1)
1
>>> next(i1)
2
>>> i2 = iter(r)
>>> next(i2)
0
>>> next(i1)
3

reversed, однако по определению возвращает итератор. При необходимости он может вызвать iter для своего итеративного аргумента, чтобы заставить итератор развернуться. Он также может использовать метод __reversed__ своего аргумента для получения обратного итератора. range.__reversed__ дает итератор, подобный range.__iter__, но идущий в противоположном направлении.

0 голосов
/ 30 января 2020

Потому что, согласно reversed() документам:

Вернуть обратный итератор.

range() однако возвращает неизменяемую последовательность.

next() можно использовать только для объектов с методом __next__().

...