2012-04-25 2 views
8

Учитывая следующую функцию f с двумя аргументами, каков стандартный способ применения карты только к x?Применение карты для частичного аргумента

def f (x,y): 
    print x,y 

Более конкретно, я хотел бы выполнить следующую операцию с картой в одной строке.

list=[1,2,3] 
fixed=10 
for s in list: 
    f(s,fixed) 

Один из способов сделать это:

import functools 
map(functools.partial(lambda x,y:f(y,x),fixed),list) 

Что лучше?

ответ

14

Прежде всего, нет необходимости использовать лямбда и частичное - они являются альтернативы:

map(lambda x:f(x,fixed),srclist) 

Во-вторых, вы можете просто связать второй аргумент с partial, до тех пор, как вы знаете имя аргумента:

map(functools.partial(f,y=fixed),srclist) 

в качестве альтернативы, используйте список понимание:

[f(x, fixed) for x in srclist] 
+1

Можете ли вы прокомментировать, как производительность этих трех методов складывается? – chase

+1

@chase Ну, последнее не связано с фактическим частичным приложением, поэтому оно позволяет избежать накладных расходов. Что касается двух других, я не могу сказать. Такая микро-оптимизация не должна произойти, пока вы не определите точку доступа в любом случае. – Marcin

+0

Вообще я согласен. Хотя изредка каждый раз просматривает 2-летние SO-вопросы, когда они нашли точку доступа;) Должно быть достаточно легко профилировать, хотя я лично предпочитаю последнее решение для ясности. – chase

5
map(lambda x: f(fixed,x), thelist) 

Или даже не используйте map(), вместо этого используйте вместо этого список списков.

[f(fixed, x) for x in thelist] 

PS: не используйте list в качестве имени переменной, это важный встроенный имя (тип списка).

1

Что случилось с:

def add(x, y): 
    return x + y 

l = [1, 2, 3] 

from functools import partial 
plus10 = map(partial(add, y=10), l) 
print plus10 

## [11, 12, 13] 
+0

Это нечитаемо (и я думал, что python сам объясняет?). Примеры понимания списка более читабельны. – Ingo

+0

@Ingo: Конечно, кроме ОП не говорил ничего о понимании. – georg

5

Учитывая следующие функции F с двумя аргументами, что является стандартным способом, чтобы применить карту только х?

Немного обсуждение выделки и частичного применения

С точки FP, ваша функция f является "uncurried" - в то время как он концептуально принимает два аргумента, они связаны в единую структуру продукта. В Python все небрежно, все время. Вы должны сразу дать все аргументы, или ни один из них.

Чтобы обойти это, существуют различные трюки, но концептуально вы просто хотите «карри» функции. То есть преобразуйте f(x,y) в f(x), который возвращает новую функцию g(y).

В языках, которые каррированы, вы можете написать этот перевод легко, как:

-- curry: take a function from (x,y) to one from x to a function from y to z 
curry :: ((x,y) -> z) -> (x -> y -> z) 
curry f x y  = f (x, y) 

Так curry принимает ваши кэрри f и аргументы продукта, отдельно, и применяет аргументы, как только все они доступны. Противоположное также довольно легко:

uncurry :: (x -> y -> z) -> ((x,y) -> z) 
uncurry f (x,y) = f x y 

Как это относится к частичным приложениям?

  • Каррирования принимает функцию, которая принимает структуру (п -продуктового) аргумент, и возвращает новую функцию, принимая п аргументов.
  • Частичное применение берет функцию п аргументов и применяет их к к аргументов, что дает функцию п-к остальных аргументов.

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

Я думаю, что более гибко быть в среде с картой по умолчанию, поскольку частичное приложение является бесплатным. В такой среде обычно объединяются функции, которые modify a data structure into a pipeline. Например. трубопровод целочисленных модификаций:

(+1) . (*2) . (^3) $ 7 

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

Смежные вопросы