Введение в язык Питон
773123a3

Другие функции высшего порядка


Помимо фундаментальной функции curry(), в модуль functional включает ряд интереснейших функций высшего порядка. Более того, не составляет большого труда самому написать свои собственные функции высшего порядка - с помощью или без этого модуля. Во всяком случае, можно воспользоваться идеями, представленными в нем.

По большей части функции высшего порядка ведут себя как "усовершенствованные" версии стандартных функций map(), filter()

и reduce(). В большинстве случаев они действуют согласно следующему правилу: "принять функцию или функции и некоторые списки в качестве параметров, затем применить функцию (функции) к списку параметров". Это правило предоставляет потрясающие возможности для программирования. Другой принцип "принять набор функций и создать функцию, комбинирующую их функциональность". И опять-таки, возможны многочисленные вариации. Давайте взглянем, что предоставляет functional.

Функции sequential() и also() создают функцию, основанную на последовательность других функций. Функции-компоненты затем могут быть вызваны с одинаковым аргументом (аргументами). Главное различие между этими двумя функциями заключается в том, что в sequential() список функций принимается в качестве первого аргумента, а also() принимает список аргументов (каждый из которых должен быть функцией) переменной длины. В большинстве случаев их используют ради побочных эффектов составляющих функций, однако sequential() позволяет опционально задать, результат какой функции вернуть как комбинированное значение:

    #---- Sequential calls to functions (with same args) ----#

          >>> def a(x):

          ...     print x,

          ...     return "a"

          ...

          >>> def b(x):

          ...     print x*2,

          ...     return "b"





          ...

          >>> def c(x):

          ...     print x*3,

          ...     return "c"

          ...

          >>> r = also(a,b,c)

          >>> r

         

          >>> r(5)

          5 10 15

          'a'

          >>> sequential([a,b,c],main=c)('x')

          x xx xxx

          'c'


Функции disjoin() и conjoin()  схожи с sequential() и also() в том смысле, что они также создают новые функции, которые применяют параметр(ы)  к нескольким составляющим функциям. Но disjoin()

выясняет, возвращает ли хотя бы одна из составляющих функций "истину" (true), а conjoin()  выясняет, возвращают ли все

функции "истину". При этом, когда это возможно, логика "короткого замыкания", поэтому при их вызове часть побочных эффектов может не проявиться. joinfuncs()

похожа на also(), но, в отличие от нее, возвращает кортеж результатов составляющих функций, а не выбирает одно значение.

В то время как вышеуказанные функции вызывают много функций с одинаковыми параметрами, функции any(), all() и none_of()

позволяют вызывать одну и ту же функцию для каждого значения из списка. В общем случае они подобны встроенным функциям map(), filter()

и reduce(). Но, в отличие от последних, эти функции задают булевы (логические) вопросы касательно набора возвращаемых величин. Например,



    #--------- Ask about collections of return values -------#

          >>> from functional import *

          >>> isEven = lambda n: (n%2 == 0)

          >>> any([1,3,5,8], isEven)



          1

          >>> any([1,3,5,7], isEven)

          0

          >>> none_of([1,3,5,7], isEven)

          1

          >>> all([2,4,6,8], isEven)

          1

          >>> all([2,4,6,7], isEven)

          0


Особый интерес для тех, кто неравнодушен к математике, представляет функция высшего порядка compose(). Композиция из нескольких функций формирует цепочку, направляя возврат одной функции на вход следующей. Программист, комбинирующий несколько функций, должен следить за тем, чтобы выход и вход соответствовали друг другу - но ведь это так в любом случае, если программист использует возвращаемое значение. Ниже приведен пример, поясняющий сказанное:



    #----------- Creating compositional functions -----------#

          >>> def minus7(n): return n-7

          ...

          >>> def times3(n): return n*3

          ...

          >>> minus7(10)

          3

          >>> minustimes = compose(times3,minus7)

          >>> minustimes(10)

          9

          >>> times3(minus7(10))

          9

          >>> timesminus = compose(minus7,times3)

          >>> timesminus(10)

          23

          >>> minus7(times3(10))

          23




Содержание раздела