Функция itertools.islice
может создавать срез из любой итерации. Утверждение:
itertools.islice(lst, 0, None, 2)
В упрощенном выражении означает «вернуть итератор, который при оценке вернет все остальные элементы в lst, начиная с элемента в 0». 0
arg - это начальная точка, а 2
- это значение шага (сколько пропустить, чтобы получить следующее значение)
Было бы лучше использовать список из 6 элементов для иллюстрации, поскольку, глядя на [(1, 2), (1, 5)]
, может быть неясно, какая функция создает внутренние кортежи (они не создаются до окончательного izip).
>>> lst = [1, 2, 3, 4, 5, 6]
>>> list(itertools.islice(lst, 0, None, 2))
[1, 3, 5]
>>> list(itertools.islice(lst, 0, None, 2))
[2, 4, 6]
Будьте осторожны, используя это с генератором; первый вызов пройдет всю последовательность, опустошив генератор:
>>> def foo():
... for i in range(6):
... yield i + 1
>>>
>>> gen = foo()
>>> list(itertools.islice(gen, 0, None, 2)
[1, 3, 5]
>>> list(itertools.islice(gen, 1, None, 2)
[]
Ваша функция должна производить 2 последовательности, шансы и четности. Вот где приходит понимание списка:
>>> [itertools.islice(lst, i, None, 2) for i in range(2)]
[<itertools.islice object at 0x7f958a79eaf8>, <itertools.islice object at 0x7f958a79eaa0>]
Теперь у вас есть 2 объекта островков, готовых к перемежению. Для этого мы могли бы использовать zip
, но itertools.izip
более эффективно, поскольку возвращает итератор:
>>> list(zip([1, 3, 5], [2, 4, 6]))
[(1, 2), (3, 4), (5, 6)]
>>> tmp = itertools.izip(*[itertools.islice(lst, i, None, 2) for i in range(2)])
>>> tmp
<itertools.izip object at 0x7f958a7b6cf8>
>>> list(tmp)
[(1, 2), (3, 4), (5, 6)]
Надеюсь, это поможет прояснить шаги.