Порядок аргументов функций фильтра Python
Python's filter и функции itertools.ifilter имеют следующие подписи:
filter(function, iterable)
itertools.ifilter(predicate, iterable)
Есть ли причина разместить predicate
аргумент перед iterable
? В таком случае нельзя пропустить predicate
аргумент для упрощения filter(bool, [0, 1, 0, 2])
призыв к просто filter([0, 1, 0, 2])
, Второй для меня выглядит более идиоматичным.
1 ответ
Это помогает понять парадигму, из которой filter
был заимствован. Вместо того, чтобы думать о filter
как функция, которая принимает функцию и список в качестве двух аргументов, думайте о ней как о функции, которая принимает один аргумент, предикат. Возвращаемое значение - это новая функция, которая берет список и возвращает новый список. В этом смысле, filter
это функция (на самом деле, функтор), которая "поднимает" функцию в новую "категорию".
Например, предположим, у вас есть предикат is_even
, который принимает целое число в качестве аргумента и возвращает истину, если аргумент четный, ложь, если он нечетный. затем filter(is_even)
можно рассматривать как возвращение функции, которая принимает список целых чисел и возвращает список логических значений, причем каждый элемент указывает на четность соответствующего элемента ввода. Вы можете применить эту функцию к списку, чтобы filter(is_even)(list_of_ints)
идентично filter(is_even, list_of_ints)
в Python. Этот метод разложения многоаргументной функции на ряд функций с одним аргументом называется каррированием.
filter
Тип подписи отражает ее происхождение и отсутствие встроенного каррирования в Python. Вы можете смоделировать это, используя functools.partial
, что позволяет частично применить функцию, предоставляя аргументы слева направо для определенных параметров.
from functools import partial
x = partial(filter, is_even) # lambda lst: filter(is_even, lst)
new_list = x(list_of_ints)
# or just new_list = partial(filter, is_even)(list_of_ints)