предикатная функция loop_ while в python внутри stdlib - PullRequest
0 голосов

У меня есть определенное ограничение в моем проекте, что я не могу использовать операторы / ключевые слова, такие как while, поэтому мне интересно, существует ли функция, которая работает аналогично приведенному ниже примеру кода в стандартной библиотеке, то есть functools, itertools и т. Д .?

>>> # signature: loop_while(pred, g, f, *args, **kwargs)
>>> loop_while(lambda r: r != 0,  # predicate
...            lambda v: v - 1,  # modifier function
...            lambda: 5  # initial function
... )

Где loop_while может быть определено как нечто, примерно похожее на

def loop_while(pred, g, f, *args, **kwargs):
   res = f(*args, **kwargs)
   while pred(res):
       res = g(res)

, что функционально эквивалентно:

n = 5
while n != 0:
    n -= 1

Или другое решение, которое позволит вам выполнить предикатный цикл в одной строке, например, [<expr> while <pred>], но используя любые возможные приемы.

1 Ответ

0 голосов
/ 24 мая 2018

Модуль itertools (на удивление) не предоставляет рецепт для следующей функции, которая обеспечивает повторяемость, состоящую из x, g(x), g(g(x)) и т. Д .:

def iterate(g, x):
    yield x
    for y in iterate(g(x), g):
        yield y

(Вышеприведенное предоставлено сторонним модулем toolz.itertoolz. Его определение чище, чем у меня:

def iterate(g, x):
    while True:
        yield x
        x = g(x)

)

Тогда ваша функция - это просто композиция iterateи itertools.takewhile:

def loopwhile(pred, g, f, *args, **kwargs):
    for x in itertools.takewhile(pred, iterate(g, f(*args, **kwargs))):
        yield x

Например,

>>> list(loopwhile(lambda x: x < 1024, lambda x: x * 2, lambda: 1))
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]

Вышеприведенные версии Python 3 немного проще:

def iterate(g, x):
    yield x
    yield from iterate(g, g(x))

def loopwhile(pred, g, f, *args, **kwargs):
    yield from takewhile(pred, iterate(g, f(*args, **kwargs)))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...