Подтвердить что ты не робот

Как получить результаты от вложенной функции генератора?

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

import time

def GeneratorFunction(max_val):
    for i in range(0,5):
        time.sleep(1)
        yield "String %d"%i

def SmallGenerator():
    yield GeneratorFunction(3)

for s in SmallGenerator():
    print s

... почему это не так просто напечатать 5 строк, которые я ожидаю? Вместо этого он возвращает функцию генератора:

<generator object GeneratorFunction at 0x020649B8>

Как я могу заставить это привести строки, поскольку нормальная функция генератора будет?

4b9b3361

Ответ 1

ОБНОВЛЕНИЕ На основе комментария @Martin Pieters, гораздо лучший подход будет просто.

def SmallGenerator(): return GeneratorFunction(3)

SmallGenerator должен быть что-то вокруг:

def SmallGenerator():
    for item in GeneratorFunction(3):
        yield item

В вашей реализации SmallGenerator выдает фактический генератор, а не элементы, сгенерированные им.

Ответ 2

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

import time

def GeneratorFunction(max_val):
    for i in range(0,max_val):
        time.sleep(1)
        yield "String %d"%i

def SmallGenerator():
    return GeneratorFunction(3) # <-- note the use of return instead of yield

for s in SmallGenerator():
    print s

Ответ 3

Возможно, вам придется использовать новый yield from, доступный с Python 3.3, называемый делегированный генератор.

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

Я хотел сделать что-то вроде этого:

def f():

    def g():

        do_something()
        yield x
        …
        yield y

    do_some_other_thing()
    yield a
    …
    g()  # Was not working.
    yield g()  # Was not what was expected neither; yielded None.
    …
    yield b

Теперь я использую это вместо:

yield from g()  # Now it works, it yields x and Y.

Я получил ответ с этой страницы: Python 3: Использование "yield from" в Generators - Part1 (simeonvisser.com).

Ответ 4

Пришел сюда искать другую форму "вложенной доходности" и, наконец, нашел скрытый ответ. Не может быть лучшим, но он работает.

Я хотел уступить через дерево реестра, и вот решение.

        def genKeys(key):
            for value in key.values():
                yield value
            for subkey in key.subkeys():
                print(subkey)
                for x in genKeys(subkey): #this is the trick
                    continue

Ответ 5

Вот еще один небольшой пример для создания таблицы умножения от 1 до 10:

class Gen1:

    def __init__(self, gen2):
        self.gen2 = gen2

    def __iter__(self):    
        for a in range(1, 11):    
            for b in self.gen2:
                yield a * b


class Gen2:    

    def __iter__(self):
        for a in range(1, 11):
            yield a


def main():

    gen2 = Gen2()
    gen1 = Gen1(gen2)

    for v in gen1:
        print(v)

if __name__ == '__main__':
    main()

Ответ 6

Я пришел в поисках другого использования вложенных доходностей..

list_of_lists = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9],
]

def iter_all(foo):
    yield foo

    if isinstance(foo, list):
        for i in foo:
            for x in iter_all(i):
                yield x


print([i for i in iter_all(list_of_lists)])

выход:

[[[1, 2, 3], [4, 5, 6], [7, 8, 9]], [1, 2, 3], 1, 2, 3, [4, 5, 6], 4, 5, 6, [7, 8, 9], 7, 8, 9]