Пишите чистый и функциональный код на Python, используя концепцию функций высшего порядка, как в JavaScript.

Как можно использовать функции высшего порядка (функции, возвращающие другие функции) в Python?

Это мой пример JavaScript, концепцию программирования которого я хотел бы использовать и в Python. Допустим, например, что я хотел бы обернуть строку в элемент HTML. В JavaScript это будет выглядеть так:

var wrapInElement = function(ele) {
    return function(inp) {
        return "<" + ele + ">" + inp + "</" + ele + ">";
    };
};

И тогда я бы использовал это так:

var names = ["Mike", "Tony", "John"];
names.map(wrapInElement("p"));

Как это может выглядеть в Python? Есть ли способ написать функции, которые возвращают настраиваемые функции, как в примере выше? Можно также написать класс на Python, который выполняет эту задачу, но не будет ли это слишком много для такой простой задачи?


person Xiphias    schedule 19.11.2013    source источник
comment
Вы пытались перевести свой код JS на Python? ты вообще что-нибудь пробовал?   -  person Peter Varo    schedule 19.11.2013
comment
На самом деле, я был настолько уверен, что это не сработает, что не стал пробовать то, что было предложено в качестве решения. Я, вероятно, должен был это сделать, так как это действительно можно перевести один в один.   -  person Xiphias    schedule 19.11.2013


Ответы (2)


В python функции являются гражданами первого класса, как и в javascript:

def adder(n):
    def add_func(x):
        return x + n
    return add_func

add3 = adder(3)
print map(add3, [1,2,3])  # [4, 5, 6]

Это не единственный вариант, например adder можно записать и так:

def adder(n):
    return lambda x: x + n

Обратите внимание, что функциональный стиль не совсем питонический, когда это возможно, мы предпочитаем включения и генераторы функциям высокого порядка:

wrapped = ["<p>{}</p>".format(name) for name in names]
person georg    schedule 19.11.2013

Ваш пример JavaScript можно переписать (возможно, более чисто), используя частичное приложение:

// depends on `_` -- see link above
function wrapInElement(ele, inp) {
    return "<" + ele + ">" + inp + "</" + ele + ">";
};

var f = _.partial(wrapInElement, "p")

... then use f as a normal function ...

И почти так же в Python:

from functools import partial

def wrap_in_element(ele, inp):
    return "<%s>%s</%s>" % (ele, inp, ele)

f = partial(wrap_in_element, "p")

... then use f as a normal function ...

Хотя да, можно использовать функции более высокого порядка как в Python, так и в JavaScript, но если вы обнаружите, что возвращаете функции, чтобы развернуть свой собственный механизм частичного приложения, вы должны понимать, что это уродство (которое кажется в примерах обоих языков) не требуется благодаря замечательным библиотекам.

person Matt Fenwick    schedule 19.11.2013
comment
Подчеркну, что это решение еще проще, чем то, которое я отметил как правильный ответ. Я не знал частичных приложений ни в JavaScript, ни в Python. Это довольно интересно. Спасибо. - person Xiphias; 20.11.2013