составить функциональный и функциональный модуль - PullRequest
13 голосов
/ 23 января 2012

Документация Python 3.2 относится к Модуль functional Коллина Винтера , который содержит функцию compose:

Функция compose () реализует композицию функций,Другими словами, он возвращает обертку вокруг внешнего и внутреннего вызываемых элементов, так что возвращаемое значение из внутреннего передается напрямую во внешний.

К сожалению, этот модуль не обновлялся с июля 2006 года;Интересно, есть ли замена?

Пока мне нужна только функция compose.Является ли следующее оригинальное определение functional.compose все еще хорошим для Python 3?

def compose(func_1, func_2, unpack=False):
    """
    compose(func_1, func_2, unpack=False) -> function

    The function returned by compose is a composition of func_1 and func_2.
    That is, compose(func_1, func_2)(5) == func_1(func_2(5))
    """
    if not callable(func_1):
        raise TypeError("First argument to compose must be callable")
    if not callable(func_2):
        raise TypeError("Second argument to compose must be callable")

    if unpack:
        def composition(*args, **kwargs):
            return func_1(*func_2(*args, **kwargs))
    else:
        def composition(*args, **kwargs):
            return func_1(func_2(*args, **kwargs))
    return composition

Этот ТАК вопрос в некоторой степени связан;он спрашивает, должен ли Python поддерживать специальный синтаксис для compose.

1 Ответ

6 голосов
/ 01 февраля 2012

Ваша реализация compose действительна для Python 3.2, как обсуждалось в комментариях выше. Большинство функций библиотеки, которые вы дали, имеют эквивалент Python, написанный в документации .

Такие функции, как map и filter, уже реализованы в python и также могут быть просто выражены как списки. Python имеет функцию id, возвращающую идентификатор объекта (в виде целого числа), но функцию id библиотеки можно выразить как lambda x: x.

Другие модули, которые могут вас заинтересовать, это itertools и functools, в которых есть partial и reduce (что аналогично foldl, но порядок аргументов не тот же).

Вот простые реализации некоторых из них, которые я не нашел в стандартной библиотеке:

from functools import reduce

def flip(f):
    if not callable(f):
        raise TypeError("Cannot filp a non-callable object")
    def result(*args, **kw):
        args = list(args)
        args.reverse()
        return f(*args, **kw)
    return result

def ilast(i):
    return reduce(lambda _, x: x, i)

def iscanl(f, v, seq):
    yield v
    for a in seq:
        v = f(v, a)
        yield v

def scanl(*args, **kw):
    return list(iscanl(*args, **kw))

def foldl(*args, **kw):
    return ilast(iscanl(*args, **kw))
# Or using reduce
#def foldl(f, v, seq):
#    return reduce(f, seq, v)

def iscanr_reverse(f, v, seq):
    return iscanl(flip(f), v, seq)

def scanr(*args, **kw):
    result = list(iscanr_reverse(*args, **kw))
    result.reverse()
    return result

def foldr(*args, **kw):
    return ilast(iscanr_reverse(*args, **kw))
...