#python #lambda #functional-programming
#python #лямбда #функциональное программирование
Вопрос:
Я пересматриваю некоторые упражнения scheme на python (если это имеет смысл), чтобы выяснить, что python может делать с точки зрения FP. Моя проблема касается лямбда в python: могу ли я определить общую функцию в python с оператором в качестве одного из аргументов?
Подумайте об этом :
def f (op,x,y):
#return some lambda function that combines x and y in the appropriate way
#i.e if op is , then return x y, if op is -, then return x-y etc
#Edit : added usage
#this should be called like this:
f( , 1,2) #should return 3
Я знаю, что это возможно в scheme, но есть ли что-то эквивалентное в python? У меня сложилось впечатление, что lambda в python — это просто более короткий способ определения метода, и я не нашел никакого способа определить общую функцию объединения в python.
Комментарии:
1. Стоит отметить, что наиболее часто используемые лямбды имеют встроенные функции :
sum()
,any()
,all()
Ответ №1:
Я вижу некоторые моменты в вашем вопросе, давайте пройдемся по ним по порядку:
1. Могу ли я передать кому-либо функцию в качестве параметра?
ДА:
def f(op, x, y):
return op(x, y)
def add(x, y):
return x y
f(add, 10, 7) #gives 17
2. Что тогда насчет операторов?
В отличие от scheme, операторы Python не являются функциями, поэтому вы не можете передавать их напрямую в качестве параметров. Вы можете либо создать функции-оболочки самостоятельно, либо импортировать модуль operator из стандартной библиотеки.
import operator
operator.add(1, 2)
(lambda x,y : x y)(1, 2)
Операторы, не являющиеся реальными функциями, в большинстве случаев немного печальны, но, по крайней мере, Python дает нам цепные сравнения, как 10 <= x < 100
в exchange…
3. Итак, в чем разница между Python и Scheme?
В общем смысле функции в Python такие же мощные, как и функции в Scheme, однако есть некоторые вещи, на которые следует обратить внимание:
Ключевое слово lambda ограничено
В качестве тела функции может быть только одно выражение
f = lambda x, y: x y
Поскольку в Python есть множество вещей, которые являются операторами, а не выражениями (присваивания, 2.x print
, …), вам часто приходится вместо этого возвращаться к именованным функциям.
Есть замыкания
def make_printer(msg):
def printer():
print msg
return printer
printer('a message')()
Но изменение переменных в них — это боль
Это не работает. Он пытается привязать новый n для внутренней функции вместо использования внешней
def make_counter(n):
def inc():
n = n 1
return n
return inc
новое нелокальное ключевое слово 3.x
def make_counter(n):
def inc():
nonlocal n
n = n 1
return n
return inc
обходной путь с изменяемыми объектами
def make_counter(n):
nw = [n]
def inc():
nw[0] = nw[0] 1
return nw[0]
return inc
Объекты вместо замыканий. Использует волшебный __call__
метод, чтобы притвориться функцией
class Counter:
def __init__(self, n):
self.n = n
def __call__(self):
self.n = 1
return self.n
Комментарии:
1. Спасибо, я понял, как сделать что-то эквивалентное схеме (но не такое элегантное)
2. «У вас может быть только одно выражение в качестве тела функции» Ну, технически в Scheme все является выражением (
set!
вызов — это выражение; и вы можете объединить несколько «операторов» вместе, используяbegin
, что также создает выражение). Так что в этом отношении это не так уж и отличается3. @newacct: Да, но многие вещи, которые являются выражениями в scheme, не являются выражениями в python. Лямбды Python более ограничены в том, что они могут делать.
Ответ №2:
Операторы на самом деле не являются функциями в python, больше похожи на методы — x y
это сокращение от x.__add__(y)
, или y.__radd__(x)
. Вы можете использовать функции в operator
модуле для эмуляции желаемого поведения.
Комментарии:
1. Хороший ответ. Рассмотрите возможность добавления примера f=lambda op,x,y: op(x,y); f(operator.add, 1, 2)
Ответ №3:
Я думаю, что лучше всего сделать функцию, которая выполняет оператор, и передать это:
def f(op, x, y):
return op(x, y)
f(lambda x, y: x y, 1, 2)
Выглядит немного излишним, хотя, когда вы можете сделать:
f = lambda x, y: x y
f(1, 2)
Комментарии:
1. Нет. Все эти функции уже существуют в
operator
модуле.
Ответ №4:
Вы не можете синтаксически передать оператор в python. Например f( )
, это синтаксическая ошибка. Однако, если вы считаете, что op — это любая функция, вы можете использовать def или lambda:
def f(op, x, y):
def op_func():
return op(x, y)
return op_func
or
def f(op, x, y):
op_func = lambda: op(x, y)
return op_func
В вашем случае вы хотите оценить функцию:
def f(op, x, y):
return op(x, y)
Помните, что Python интерпретируется, поэтому даже операторы def оцениваются во время выполнения.
[Если по какой-то причине вам нужно, вы можете получить доступ к встроенным операторам как функциям, используя модуль operator: http://docs.python.org/library/operator.html ]
Ответ №5:
Проверьте operator
модуль. Все операторы python доступны там в виде функций. пример:
import operator
operate = lambda op, x, y: op(x, y)
operate(operator.add, 1, 2)
Комментарии:
1. Ваш ответ верен, но он не отвечает на мой вопрос. Точнее, мой вопрос заключается в том, как и могу ли я определить общую объединяющую функцию в python 🙂 Я хочу сделать что-то вроде сворачивания (за исключением того, что я просто хочу сделать это для 2 переменных вместо структуры данных): haskell.org/haskellwiki/Fold