zip(*[a.__iter__()]*3)
Не смотря на внешнюю простоту, это очень интересная (и иногда полезная) конструкция Python. На собеседованиях мы просим объяснить как она работает, если человек справляется, это хороший знак.
Полный пример работы алгоритма кластеризации:
>>> a = [1,2,3,4,5,6,7,8,10]
>>> zip(*[a.__iter__()]*3)
[(1, 2, 3), (4, 5, 6), (7, 8, 10)]
Разберем эту конструкцию по частям.
__iter__()
Возвращает объект-итератор для списка (кортежа или любого другого итерируемого элемента).
Этот метод используется интерпретатором, когда список попадает, например, в цикл for.
Сам объект итератор имеет метод next(), который один за другим возвращает элементы списка.
[]*3
Операция умножения для списков формирует новый список, используя элементы начального заданное количество раз.
>>> [1,2,3] * 3
[1, 2, 3, 1, 2, 3, 1, 2, 3]
Здесь важный момент: все идентификаторы в Python — это ссылки. То есть конструкция [a.__iter__()]*3 даст нам список из трех ссылок на один и тот же итератор списка. Небольшой пример:
>>> iters = [a.__iter__()]*3
>>> print iters
[, , ]
>>> (iters[0].next(), iters[1].next(), iters[2].next())
(1, 2, 3)
*
Превращает итерируемый объект в список неименованных аргументов функции.
Одна из моих любимых возможностей Python. Следующие конструкции эквивалентны:
my_func(*[1,2,3])
my_func(1,2,3)
zip
zip возращает список кортежей, где i-тый кортеж состоит из i-тых элементов каждого из агрументов функции. Например:
>>> zip((1,2), (3,4), (4,5))
[(1, 3, 4), (2, 4, 5)]
В официальной описана последняя особенность, благодаря которой кластеризация работает.
The left-to-right evaluation order of the iterables is guaranteed. This makes possible an idiom for clustering a data series into n-length groups using zip(*[iter(s)]*n).
Как вы заметили, там содержится и рассматриваемая нами конструкция. Так что это не какой-нибудь однострочник на Perl, а вполне официальная особенность. Пользуйтесь на здоровье.
А какие интересные конструкции Python знаете вы?
Добавить комментарий