лямбда в python

#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