Результат работы функции итератора инвертируется

Появилась необходимость последовательно сравнить элементы двух списков по соответствующим индексам. Использовал комбинацию функций map() и next() :

# Последовательное сравнение элемента по совпадающими индексами двух списков. T.к. map() возвращает объект итератор, таковой необходимо пропустить через next()
g = map(lambda y: y,[1,2,4,3,4,5,6,4,4]) # то же самое можно записать как iter([1,2,4,3,4,5,6,4,4])
s = [i for i in map(lambda x: x == next(g), [1,2,4,3,4,5,6,4,5])]
print(s)
#Вывод: [True, True, True, True, True, True, True, True, False]

Однако при подстановке в генератор списка самой функции map() вместо промежуточной переменной g вывод диаметрально противоположный:

s = [i for i in map(lambda x: x == next(map(lambda y: y,[1,2,4,3,4,5,6,4,4])), [1,2,4,3,4,5,6,4,5])]
print(s)
#Вывод: [True, False, False, False, False, False, False, False, False]

Почему так происходит?


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

Автор решения: Stanislav Volodarskiy

В первом случае последовательные вызовы next(g) извлекают из g элементы один за другим. То есть вы сравниваете два списка поэлементно.

Во втором случае каждый вызов лямбды создаёт новый генератор из которого всякий раз извлекается первое значение. То есть вы сравниваете все элементы второго списка с первым элементом первого списка, с единицей.

P.S. Вас смущает что подстановка выражения на место переменной меняет смысл программы? Согласен. Но "правило подстановки" действует только для вычислений без побочных эффектов. Если все элементы выражений – чистые функции, вы можете свободно делать подстановки, смысл программы останется неизменным. В вашем случае вызов next(g) обладает побочным эффектом: он меняет состояние генератора g. А это значит, что "правило подстановки" здесь может не сработать, и действительно не работает.

P.P.S. Классическое решение вашей задачи:

s = [x == y for x, y in zip(list1, list2)]
→ Ссылка