Работает ровно так, как и должно. Ибо Пайтон - язык динамический. Чтобы разобраться в проблеме, надо понимать как именно работают функции и их аргументы. (1) обычные аргументы резолвятся во время вызова функции, (2) дефолтные аргументы резолвятся во время определения функции, (3) нелокальные переменные внутри функции резолвятся во время работы функции (ищутся во внешнем или глобальном пространствах имен). Не соображу, какое слово подобрать вместо "резолвятся". Вот третий вариант и работает в приведенном коде, а должен работать второй.
Следовательно, надо писать не так:
lambda c: c.data == food
а вот так:
lambda c, food=food: c.data == food
Ну, и простой пример для воспроизведения такого эффекта:
from typing import List
def f_1(lst: List) -> None:
funcs = list()
for val in lst:
funcs.append(lambda: val)
# цикл закончился, val имеет значение последнего элемента из списка
for func in funcs:
print(func())
def f_2(lst: List) -> None:
funcs = list()
for val in lst:
funcs.append(lambda val=val: val)
for func in funcs:
print(func())
if __name__ == '__main__':
data = ['apple', 'tomato', 'potato']
print("\nf_1:")
f_1(data)
print("\nf_2:")
f_2(data)