Что произойдет, если передать в filter функцию без вызова в Python
Что проверяют
Понимаете ли вы, что функция в Python это обычный объект, и различаете ли имя функции и её вызов. Заодно смотрят, помните ли про ленивость filter: ошибка в аргументе всплывает не там, где её ждут.
Как отвечать
Начните с того, что в формулировке спрятана подмена. filter(function, iterable) ждёт именно объект функции, поэтому передача без скобок это и есть правильный вызов:
def is_even(n):
return n % 2 == 0
print(list(filter(is_even, [1, 2, 3, 4]))) # [2, 4]Со скобками вы сначала выполняете функцию и передаёте её результат. Что случится дальше, зависит от функции:
- есть обязательные аргументы: падение произойдёт раньше, чем управление дойдёт до
filter, это обычныйTypeErrorо недостающем аргументе; - возвращается не вызываемый объект:
filterсоздастся молча, аTypeErrorвылезет только при обходе результата, вlist()или в цикле; - возвращается
None: ошибки не будет вообще.filter(None, iterable)это документированный особый случай, он оставляет элементы, истинные сами по себе. Тихий неверный результат хуже падения.
Закончите тем, что filter возвращает итератор, а не список. Печать даёт объект фильтра, а второй проход по нему даёт пустоту, потому что итератор уже исчерпан.
Где спотыкаются
Считают, что filter отработал в момент вызова. Он ничего не вычисляет, пока результат не начали обходить, поэтому и ошибка в переданном объекте, и исключение внутри самой функции проявляются строкой с list(), а не строкой с filter.
Второе: не знают особый случай с None и принимают его за ошибку в коде. Обратная сторона той же незнакомой детали: функция, которая ничего не возвращает, неявно отдаёт None, и фильтрация тихо превращается в отбор по истинности.
Третье: доводят правило до абсурда и считают скобки ошибкой всегда. Вызов, возвращающий функцию, это нормальный приём: фабрика вроде make_checker(10) отдаёт готовый предикат, и её результат передаётся в filter совершенно законно.