Почему при сравнении чего-то с list(filter(...)) и сравнении списка от list(filter(...)) с чем-то получаются разные ответы?

Хотел сделать программу, которая бы считывала файл и возвращала бы цифры, исключая 0, не использованные в файле. Сделал ее в списочном выражении с использованием filter.

print([i for i in '123456789' if i not in list(filter(lambda x: x in 
      '123456789' and x.isdigit(), file.read()))])

в файле было 13 12. Если вместо

list(filter(lambda x: x in '123456789' and x.isdigit(), file.read()))

подставить ['1', '3', '1', '2'], то ответы будет верным, хотя питон говорит, что список и то, что возвращает функция идентично. Я знаю, что можно переделать не в 1 строчку, но хотелось бы узнать причину данного явления.


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

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

Пишем тест:

import sys


def read(file):
    t = file.read()
    print('read file, text is', repr(t))
    return t


file = sys.stdin

print([i for i in '123456789' if i not in list(filter(lambda x: x in 
      '123456789' and x.isdigit(), read(file)))])

Запускаем:

$ echo 1312 | py temp.py
read file, text is '1312\n'
read file, text is ''
read file, text is ''
read file, text is ''
read file, text is ''
read file, text is ''
read file, text is ''
read file, text is ''
read file, text is ''
['2', '3', '4', '5', '6', '7', '8', '9']

Файл читается девять раз. Первый раз нормально, остальные восемь раз получается пустая строка. Потому что файл уже прочитан.

Нужно решение с одним чтением. Или читайте один раз до печати или так:

print(sorted(set('123456789') - set(filter(lambda x: x.isdigit(), file.read()))))
→ Ссылка