2014-11-15 2 views
3

У меня есть следующие функции:Можно ли выразить эту функцию с помощью генератора?

def infinite_sequence(starting_value, function): 
    value = starting_value 
    while True: 
     yield value 
     value = function(value) 

Можно ли выразить это как генератор понимания? Если бы мы имели дело с фиксированным диапазоном, вместо бесконечной последовательности, он может рассматриваться как так: (Edit: на самом деле это не так)

(function(value) for value in range(start, end)) 

Но так как мы имеем дело с бесконечной последовательностью, можно ли это выразить, используя понимание генератора?

+0

Это почти * 'itertools.accumulate', но с достаточными различиями, чтобы подражать одному с другим больнее, чем это стоит. Я не думаю, что есть выражение генератора, особенно не тот, который читается лучше этой очень простой и идиоматической функции. – delnan

+1

Замечание по терминологии: нет такого понятия, как понимание генератора. Вы хотите использовать генератор * выражение *, который синтаксически выглядит как * list *. – chepner

+0

Почему бы не оставить его как функцию? – wwii

ответ

-1

Да, используйте бесконечный итератор, такой как itertools.count.

(function(value) for value in itertools.count(starting_value)) 
+1

-1 Это дает 'f (0)', 'f (1)', 'f (2)' вместо '0',' f (0) ',' f (f (0)) ',' f (f (f (0))) '(с' start_value = 0' для простоты). – delnan

1

Вам потребуется какое-то выражение рекурсивного генератора:.

infinite_sequence = itertools.imap(f, itertools.chain(x, __currentgenerator__)) 

где __currentgenerator__ гипотетической магия ссылка на выражение генератора это происходит в (Обратите внимание, что этот вопрос не то, что вы хотите, бесконечная последовательность, но последовательность определяется рекурсивно в терминах самого себя.)

К сожалению, у Python нет такой функции. Haskell является примером языка, который делает из-за своей ленивой оценки аргумента:

infinite_sequence = map f x:infinite_sequence 

Вы можете, однако, до сих пор достичь нечто подобное в Python 3 в то же время, используя def заявление, определив рекурсивный генератор.

def infinite_sequence(f, sv): 
    x = f(sv) 
    yield from itertools.chain(x, infinite_sequence(f, x)) 

(itertools.chain не является строго необходимым, вы могли бы использовать

def inifinite_sequence(f, sv): 
    x = f(sv) 
    yield x 
    yield from infinite_sequence(f, x) 

, но я пытался сохранить аромат выражения Haskell x:infinite_sequence.)

+0

Вы можете использовать 'accumulate' off-label, например. f = lambda x: 2 * x + 1; start_val = 0; list (islice (accumulate (repeat (start_val), lambda x, _: f (x)), 10)) '. – DSM

0

Это itertools.accumulate, игнорируя все но первое значение:

from itertools import accumulate, repeat 

def function(x): return x*2 
start = 1 

seq = accumulate(repeat(start), lambda last, _: function(last)) 

Просто напишите это в полном объеме.