Есть ли способ превратить список ответов из сценария в качестве значений? - PullRequest
3 голосов
/ 10 октября 2010

У меня давно запущенная программа, и я хочу, чтобы она реагировала.Алгоритм является рекурсивным, поэтому иногда даже подзадачи при более длительных вызовах могут быть длиннее, чем при более коротких циклах.Я попытался сделать это, чтобы использовать yield, но в итоге получил список, полный генераторов на различных уровнях рекурсивной структуры списка (список также многоуровневая иерархия, глубина записи вызовов).Я наконец-то сделал простую распечатку версии ответов, но в конце она распечатывает ответы.Я не должен печатать только результаты рекурсивных вызовов, также результаты должны подвергаться последующей обработке перед печатью.

Существует ли простой шаблон для вызова функции верхнего уровня для получения значений, но рекурсивные вызовы для возврата ответов?Должен ли я использовать for для зацикливания результатов рекурсивных вызовов или сделать list () ответов из рекурсивных вызовов?Должен ли я просто поместить параметр глубины и вернуться с глубиной> 0 и получить на глубине 0?

В любом случае, есть ли простой способ повернуть один ответ на вызов вывода строки, чтобы вернуть строки в основную программу Python?Или я все еще должен вернуть полный список из вызова модуля?Я мог бы легко запустить версию вызова ОС в отдельном интерпретаторе с помощью 'bg' в системе Linux, не так ли?

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

from __future__ import print_function
def subset(seq, mask):
    """ binary mask of len(seq) bits, return generator for the sequence """
    return (c for ind,c in enumerate(seq) if mask & (1<<ind))

numbers = [1, 5, 3, 9, 4]
print('Numbers: ',numbers)
print('Possible sums',min(numbers),'..',sum(numbers))

for i in range(1,2**len(numbers)):
    sub = list(subset(numbers, i))
    print(sum(sub),'=',' + '.join(str(s) for s in sub))

print()
target = 11
print ('Finding subsequence for sum = %i' % target)

check = None
for check in (subset(numbers, mask)
              for mask in range(1,2**len(numbers))
              if sum(subset(numbers, mask))==target):
    print (' + '.join(str(s) for s in check), ' = ', target)
if not check:
    print('No solutions')

Ответы [ 2 ]

1 голос
/ 10 октября 2010

Вам немного не хватает подробностей о том, что вы на самом деле пытаетесь сделать, но вот мое лучшее предположение (примечание: вам потребуется Python 2.6):

def do_stuff(num):
    children = [ _do_stuff(x + 1) for x in range(num) ]
    for child in children:
        child.send(None)

    count = 0
    while children:
        child = children.pop(0)
        try:
            count += child.send(count)
        except StopIteration:
            continue
        children.append(child)

def _do_stuff(num):
    to_add = 0
    for x in range(num):
        from_parent = (yield (to_add + x))
        print "child %s got %s" %(num, from_parent)
        to_add += from_parent

Что будет работать так:

>>> do_stuff(3)
child 1 got 0
child 2 got 0
child 3 got 1
child 2 got 3
child 3 got 3
child 3 got 9

Извините, что этот пример немного сбивает с толку - мой мозг не может придумать лучший пример прямо сейчас.

Также некоторые примечания: * Дети могут дать другой генератор, который может быть добавлен в список детей * Эта реализация медленная (выталкивание из заголовка списка требует времени O (n)) - см. Модуль dequeue * child.send(None) необходим для "заправки" генераторов (то есть, выполнения до первого yield)

0 голосов
/ 10 октября 2010

Ваш вопрос не очень понятен.Может быть, это поможет.

Сделать рекурсивный генератор просто;функция просто должна перебирать себя, а не вызывать себя.Например, если вы хотите написать генератор, который сплющил дерево, он может выглядеть следующим образом:

def descendants(node):
   for child in children(node):
      yield child
      for descendant in descendants(child):
         yield descendant

Этот подход возвращает каждый узел-потомок вызывающей стороне по мере ее обнаружения.Если по какой-то причине функция children сама была генератором, который возвращал каждый узел целую секунду, функция descendants возвращала бы вызывающий узел раз в секунду.

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

for x in get_things(param):
   print x

, а функция get_things() создает потоки (или процессы) и возвращает объекты, когда потоки возвращают их.

Как функция get_things() делает это, конечно, большой вопрос, и полностью зависит от того, в чем ваша проблема на самом деле.

...