Могу ли я получить значения, используемые для построения xrange Python 2.7, из самого объекта?

Если s является объектом slice в Python, созданным с использованием либо s = slice(start, stop, step), либо (в соответствующем контексте) start:stop:step, значения, используемые для построения s, доступны из самого объекта slice как s.start, s.stop и s.step.

Аналогичные члены start, stop и step доступны для объектов range в Python 3.4 [Issue9896]. Например, range(1, 4, 2).start == 1.

Однако объекты Python 2.7 xrange не имеют членов start, stop и step. Есть ли другой способ получить значения, используемые для построения xrange, из самого объекта?


person user200783    schedule 21.04.2015    source источник
comment
Вы можете довольно легко получить значения, которые создадут эквивалентный диапазон, но не фактические используемые аргументы конструктора.   -  person user2357112 supports Monica    schedule 21.04.2015


Ответы (2)


Можно восстановить исходные аргументы start и step, но не всегда исходный аргумент stop.

Один из способов получить значения — посмотреть на метод __reduce__ (или __reduce_ex__) объекта xrange (обычно используемый для травления):

>>> x = xrange(10)
>>> x.__reduce__()[1]
(0, 10, 1)
>>> y = xrange(2, 100, 13)
>>> y.__reduce__()[1]
(2, 106, 13)

Затем start, stop, step = y.__reduce__()[1] назначит трем именам переменных соответствующие целые числа. Значения start и step всегда являются исходными значениями, которые использовались для построения объекта xrange.

stop может быть выше, чем аргумент, изначально использовавшийся для заключения контракта с объектом. Для любого xrange объекта x он равен x[-1] + step.

Как правило, невозможно восстановить исходный аргумент остановки после создания объекта xrange. Если вы изучите источник xrange, вы обратите внимание, что этот объект не хранит ссылку на конкретное значение остановки, а только на начальное значение, значение шага и общую длину итератора. Когда вызывается str или __reduce__, объект вычисляет самое последнее возможное значение остановки с помощью внутренней функции get_stop_for_range.

Это отличается от объекта range Python 3, который действительно запоминает исходный конечное значение.

person Alex Riley    schedule 21.04.2015

Это некрасиво, но вы можете разобрать str представление xrange

>>> rr = xrange(1, 4, 2)
>>> str(rr)
'xrange(1, 5, 2)'
>>> start = str(rr).split('(')[1].split(',')[0]
>>> start
1

и т.д

Обратите внимание, что max нельзя надежно найти таким образом, если в диапазоне указаны шаги. Например, в приведенном выше примере (1, 4, 2) становится (1, 5, 2) в представлении str.

person jlb83    schedule 21.04.2015