2016-11-26 17 views
2

У меня есть задание в mooc, где мне нужно закодировать функцию, которая возвращает кумулятивную сумму, совокупный продукт, максимальный и минимальный входной список.
Эта часть курса была посвящена функциональному программированию, поэтому я хотел все рассказать об этом, хотя я могу использовать другие способы.
Так что я попытался это:карта списка функций и аргументов: проблема с распаковкой

from operator import mul 
from itertools import repeat 
from functools import reduce 
def reduce2(l): 
    print(l) 
    return reduce(*l) 
def numbers(l): 
    return tuple(map(reduce2, zip([sum, mul,min, max], repeat(l,4)))) 
l=[1,2,3,4,5] 
numbers(l) 

Моя проблема заключается в том, что она не работает. zip будет пропускать только один объект для уменьшения, если я использую его внутри карты, и распаковка zip даст 4 кортежа (список функций и аргументов l), поэтому я решил уменьшить2 по этой причине, я хотел распаковать zip внутри него, но он не работал.
Python возвращает объект TypeError: int 'is is iterable
Я думал, что я могу использовать return reduce (l [0], l [1]) в reduce2, но есть все тот же Error.
Я не понимаю поведение python здесь. Если я просто использую return reduce (l), он снова возвращает TypeError: уменьшает ожидаемое как минимум 2 аргумента, получил 1

Что здесь происходит? Как я могу заставить его работать? Спасибо за помощь.

ответ

3

Эффективно, вы пытаетесь выполнить такой код:

xs = [1, 2, 3, 4, 5] 
reduce(sum, xs) 

Но sum принимает итератор и не очень совместим с прямым использованием через reduce. Вместо этого вам нужна функция, которая принимает 2 аргумента и возвращает их сумму - функцию, аналогичную mul. Вы можете получить, что с operator:

from operator import mul, add 

Тогда просто изменить sum к add в вашей программе.

BTW, функциональное программирование имеет условное соглашение об именах, которое действительно круто: x с одной стороны, и xs для их списка. Это намного лучше, чем труднодоступное имя переменной l. Также он использует единственное/множественное число, чтобы рассказать вам, имеете ли вы дело со скалярным значением или коллекцией.

+0

Большое спасибо за точность об условных обозначениях. Я не знал об этом.Хорошо сделанный для добавления, на самом деле сумма является избыточной с уменьшением, теперь я понимаю. –

2

FMc answer's правильно диагностирует ошибку в коде. Я просто хочу добавить пару альтернатив вашему подходу map + zip.

С одной стороны, вместо того, чтобы определять специальную версию reduce, вы можете использовать itertools.starmap вместо map, который разработан специально для этой цели:

def numbers(xs): 
    return tuple(starmap(reduce, zip([add, mul, min, max], repeat(xs)))) 

Однако, еще лучше было бы использовать часто игнорируется variadic version из map вместо того, чтобы вручную сжать аргументы:

def numbers(xs): 
    return tuple(map(reduce, [add, mul, min, max], repeat(xs))) 

Это по существу делает zip + starmap для вас. Что касается функционального программирования, то эта версия map аналогична функции Haskell zipWith.

+0

Я знал starmap, но не думал об этом, с другой стороны, эта версия карты была мне неизвестна. Надеюсь, что ваш ответ будет повышен. Я соглашусь с ответом FMc, поскольку он ответил сначала, но ваш «заслуживает похвалы». –