2013-04-06 5 views
0

Мне было интересно, существует ли более пифонический или альтернативный способ сделать это. Я хочу сравнить результаты с кумулятивными функциями. Каждая функция изменяет выходные данные предыдущего, и я хотел бы видеть после каждой из функций эффект. Помните, что для получения фактических результатов после запуска основных функций необходима одна последняя функция для вычисления чего-то. В коде это выглядит так (только вид псевдокод):Python 3 - альтернативы кумулятивных функций

for textfile in path: 
    data = doStuff1(textfile) 
calculateandPrint() 

for textfile in path: 
    data = doStuff1(textfile) 
    data = doStuff2(data) 
calculateandPrint() 

for textfile in path: 
    data = doStuff1(textfile) 
    data = doStuff2(data) 
    data = doStuff3(data) 
calculateandPrint() 

Как вы можете видеть, для n функций мне нужно 1/2(n(n+1)) вручную сделанные петли. Есть ли, как я уже сказал, нечто большее, чем pythonic (например, список с функциями?), Который очистит код и сделает его намного короче и управляемым при добавлении большего количества функций?

Фактический код, где documents является пользовательский объект:

for doc in documents: 
    doc.list_strippedtext = prepareData(doc.text) 
bow = createBOW(documents) 

for doc in documents: 
    doc.list_strippedtext = prepareData(doc.text) 
    doc.list_strippedtext = preprocess(doc.list_strippedtext) 
bow = createBOW(documents) 

for doc in documents: 
    doc.list_strippedtext = prepareData(doc.text) 
    doc.list_strippedtext = preprocess(doc.list_strippedtext) 
    doc.list_strippedtext = abbreviations(doc.list_strippedtext) 
bow = createBOW(documents) 

пока это лишь малая часть, больше функций должны быть добавлены.

+1

В каждом цикле вы заполняете переменную цикла, помещаете ее в 'data', но затем отбрасываете все, кроме последнего результата цикла. Если вызовы 'calculateandPrint()' имеют вместо них отступы? –

+0

Действительно, вы правы, чтобы сделать его более ясным: в каждом цикле я редактирую переменную внутри объекта, и каждый текстовый файл имеет другой объект. Таким образом, функция calculateandPrint() использует все объекты и, таким образом, использует все «данные», хотя это может быть и не ясно из моего примера. Но дело было больше в итерациях функций. – Tim

ответ

3

Вы можете определить набор цепей, применяемых с functools.reduce()

from functools import reduce 

chains = (
    (doStuff1,), 
    (doStuff1, doStuff2), 
    (doStuff1, doStuff2, doStuff3), 
) 

for textfile in path: 
    for chain in chains: 
     data = reduce(lambda data, func: func(data), chain, textfile) 
     calculateandPrint(data) 

reduce() вызов эффективно делает func3(func2(func1(textfile)) если chain содержал 3 функции.

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

Каждая итерация цикла for chain in chains представляет один из ваших doStuffx тела цикла в вашем исходном примере, но мы только петли через for textfile in pathраз.

Вы также можете поменять местами петли; в соответствии с вашим примером:

for chain in chains: 
    for doc in documents: 
     doc.list_strippedtext = reduce(lambda data, func: func(data), chain, doc.text) 
    bow = createBOW(documents) 
+0

Я думаю, что это близко к ответу, который я ищу. Я добавил фактический код, чтобы дать лучшее представление о том, что нужно сделать. Можно ли использовать цепочки с моим кодом? Так можно ли изменить содержимое объекта в цепочке? – Tim

+0

Конечно; просто замените две петли в моем ответе; переместите цепи в петлю, примените каждую цепочку к документам, после того, как внутренний цикл цикла вызовет функцию 'createBOW()' один раз в цепочке. –

+0

Да, это работает отлично. Большое спасибо :-). – Tim

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