Не пойму до конца логики в работе с итераторами

Пример кода из учебника:

def mymapPad (*seqs, pad=None):
    seqs = [list(S) for S in seqs]
    res = []
    while any(seqs):
        res.append(tuple((S.pop(0) if  S else pad) for S in seqs)             
    return res 

S1, S2 = 'abc', 'xyz123'
print (mymapPad(S1,S2, pad=99))

В результате получаем:

[(‘a’, ‘x’), (‘b’, ‘y’), (‘c’, ‘z’), (99, ‘1’), (99, ‘2’), (99, ‘3’)]

Мне не понятен данный фрагмент кода:

while any(seqs):
    res.append(tuple((S.pop(0) if  S else pad) for S in seqs)

Пожалуйста объясните, что происходит в данном фрагменте и почему именно таким образом мы должны действовать? Почему здесь метод pop() Почему после else нет двоеточия и код работает? Почему за скобки необходимо опять написать ..)for S in seqs?


Ответы (1 шт):

Автор решения: Кирилл Малышев
while any(seqs):

Цикл идёт до тех пор, пока в списке seqs есть хотя бы один непустой список.

2.

res.append(tuple((S.pop(0) if  S else pad) for S in seqs))

На каждой итерации списка мы добавляем в res такой кортеж:

tuple((S.pop(0) if  S else pad) for S in seqs)

Чтобы его создать, используется генератор:

(S.pop(0) if S else pad) for S in seqs

Тут мы проходим по элементам списка seqs (который содержит списки символов). Если элемент (то есть список символов) не пуст, то в кортеж добавляется 0-й символ этого списка, а сам символ удаляется из списка. Если пуст, то обавляется pad.

S.pop(0) if S else pad

Такое выражение является так называемым тернарным оператором. В нём происходит буквально то, что в нём написано. Если выполняется S, то возвращается S.pop(0). Иначе pad.

Этот код можно переписать так:

a = []
for S in seqs:
    if S:
        a.append(S.pop(0))
    else:
        a.append(pad)
res.append(tuple(a))
→ Ссылка