Довольно сложная конструкция для объяснения. Я попробую:
с [iter(lst)]
вы создаете список с одним элементом. Элемент является итератором по списку.
всякий раз, когда python пытается получить элемент из этого итератора, возвращается следующий элемент lst
до тех пор, пока не станет больше доступного элемента.
Просто попробуйте следующее:
i = iter(lst)
next(i)
next(i)
результат должен выглядеть так:
>>> lst = [1,2,3,4,5,6,7,8]
>>> i = iter(lst)
>>> next(i)
1
>>> next(i)
2
>>> next(i)
3
>>> next(i)
4
>>> next(i)
5
>>> next(i)
6
>>> next(i)
7
>>> next(i)
8
>>> next(i)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
StopIteration
Теперь вы создаете список, содержащий дважды точно такой же итератор. Вы делаете это с помощью itlst = [iter(lst)] * 2
попробуйте следующее:
itlst1 = [iter(lst)] * 2
itlst2 = [iter(lst), iter(lst)]
print(itlst1)
print(itlst2)
Результат будет выглядеть примерно так:
>>> itlst1 = [iter(lst)] * 2
>>> itlst2 = [iter(lst), iter(lst)]
>>> print(itlst1)
[<list_iterator object at 0x7f9251172b00>, <list_iterator object at 0x7f9251172b00>]
>>> print(itlst2)
[<list_iterator object at 0x7f9251172b70>, <list_iterator object at 0x7f9251172ba8>]
Важно отметить, что itlst1
- это список, содержащий дважды один и тот же итератор, тогда как itlst2
содержит два разных итератора.
для иллюстрации попробуйте ввести:
next(itlst1[0])
next(itlst1[1])
next(itlst1[0])
next(itlst1[1])
и сравнить его с:
next(itlst2[0])
next(itlst2[1])
next(itlst2[0])
next(itlst2[1])
Результат:
>>> next(itlst1[0])
1
>>> next(itlst1[1])
2
>>> next(itlst1[0])
3
>>> next(itlst1[1])
4
>>>
>>> next(itlst2[0])
1
>>> next(itlst2[1])
1
>>> next(itlst2[0])
2
>>> next(itlst2[1])
2
Теперь к функции zip()
(https://docs.python.org/3/library/functions.html#zip):
Попробуйте следующее:
i = iter(lst)
list(zip(i, i))
zip()
с двумя параметрами. Когда вы пытаетесь получить следующий элемент из zip
, он будет делать следующее:
- получить одно значение из итерируемого, которое является первым параметром
- получить одно значение из итерируемого, которое - второй параметр.
- возвращает кортеж с этими двумя значениями.
list(zip(xxx))
будет делать это повторно и сохранять результат в списке.
Результат будет:
>>> i = iter(lst)
>>> list(zip(i, i))
[(1, 2), (3, 4), (5, 6), (7, 8)]
Следующий используемый трюк - это *
, который используется для использования первого элемента в качестве первого параметра вызова функции, второго элемента в качестве второго параметра и т. д.) Что ** (двойная звезда / звездочка) и * (звездочка / звездочка) делают для параметров?
поэтому запись:
itlst1 = [iter(lst)] * 2
list(zip(*itlst1))
в этом случае идентична
i = iter(lst)
itlst1 = [i] * 2
list(zip(itlst1[0], itlst[1]))
, что идентично
list(zip(i, i))
, которое я уже объяснял.
Надеюсь, это объясняет большинство вышеперечисленных трюков.