2016-06-07 2 views
3

взять код:сумма Python (генератор): вызов внешней функции

SUM = sum(x() for x in xs) 

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

- это единственный способ сделать это так?

for x in xs: x.pre() 

SUM = sum(x() for x in xs) 

или

SUM = 0 
for x in xs: 
    x.pre() 
    SUM += x() 

включения x.pre в х, очевидно, возможно, но сделал бы реальный код исключительно некрасиво и трудно читать. есть ли какой-либо способ использования выражений генератора, о которых я не знаю, что позволит достичь того, чего я пытаюсь достичь?

например:

SUM = sum(x(), x.pre() for x in xs) 

то будет очевидно, просто несуммируемой кортеж генератор

+0

Другим особенно уродливым способом является 'sum ((x.pre(), x()) [1] для x в xs)' ... –

+2

Явный цикл цикла, который не использует 'sum() 'встроенный - очень хорошее решение. Это очень читаемо, и я не вижу недостатков. –

+1

@Sven: обычно я бы сказал, что имеет (незначительный) недостаток, что он использует изменяемую переменную, но так как все эти объекты 'x' изменяются в любом случае, это капля в океане рассуждений о состоянии, требуемом для чтения этого кода: -) –

ответ

1

Я бы просто использовать for -loop вы уже представлен.

Есть способы делать то, что вы хотите другими способами. Например, вы могли бы использовать functools.reduce с настраиваемой функцией здесь вместо sum:

def pre_then_add(accumulated, new_one): 
    new_one.pre() # do some stuff so we get the right value 
    return accumulated + new_one() # add the value to the accumulated sum 

, а затем это просто вопрос вызова reduce:

import functools 

functools.reduce(pre_then_add, xs, 0) 

Обратите внимание, что для этого требуется, чтобы дать «базовое значение» в противном случае функция слишком проста, но также и то, что reduce с настраиваемой функцией не обязательно является наиболее эффективным или элегантным способом.

Как указано в комментариях (спасибо @SteveJessop) другая возможность использования sum будет:

def pre_then_call(x): 
    x.pre(); 
    return x() 

sum(pre_then_call(x) for x in xs) 

Но только повторить: Я хотел бы использовать явный цикл. Это гораздо легче понять с точки зрения того, что вы делаете и почему.

+2

Аналогичным образом вы можете сделать' def pre_then_call (x): x.pre(); return x() ', затем' sum (pre_then_call (x) для x в xs) '. –

+0

@SteveJessop Я знал, что не должен был включать пример. Я только включил его, чтобы показать, как такой подход менее читабельен (на мой взгляд) и только «аутсорсинг», что на самом деле сделано. По крайней мере, до тех пор, пока он не является встроенным, где фактические соображения производительности могут оправдать такую ​​«сумму». – MSeifert

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