Сброс объекта генератора в Python

Вы неправильно поняли цикл for. Используется для повторения определенных действий, пока указанное условие не станет ложным. Ваше условие - это задание, поэтому есть ошибка.

Поэтому измените это

для ($ i = 0; $ row = $ result-> fetch (); $ i ++) {

на следующее:

foreach ($result->fetch_all() as $row) {

$ result-> fetch_all () возвращает ассоциативный массив данных. С помощью цикла foreach вы получаете доступ к каждому элементу в этом массиве и можете получить к нему доступ с помощью $ row ['any-key-you-want']

133
задан Cœur 31 August 2017 в 03:39
поделиться

6 ответов

Другой вариант - использовать функцию itertools.tee () для создания второй версии вашего генератора:

y = FunctionWithYield()
y, y_backup = tee(y)
for x in y:
    print(x)
for x in y_backup:
    print(x)

Это может быть полезно с точки зрения использования памяти если исходная итерация могла обработать не все элементы.

107
ответ дан 24 November 2019 в 00:00
поделиться

Можно сделать это при помощи itertools.cycle () , можно создать итератор с этим методом и затем выполниться для цикла по итератору, который циклично выполнится по его значениям.

, Например:

def generator():
for j in cycle([i for i in range(5)]):
    yield j

gen = generator()
for i in range(20):
    print(next(gen))

генерирует 20 чисел, от 0 до 4 неоднократно.

А отмечают в документах:

Note, this member of the toolkit may require significant auxiliary storage (depending on the length of the iterable).
1
ответ дан 24 November 2019 в 00:00
поделиться

Если ответа Гжегожа Оледски недостаточно, вы, вероятно, могли бы использовать send () для достижения своей цели. См. PEP-0342 для получения дополнительных сведений об улучшенных генераторах и выражениях yield.

ОБНОВЛЕНИЕ: См. Также itertools.tee () . Это связано с некоторыми из упомянутых выше компромиссов между памятью и обработкой, но может сэкономить некоторую память вместо простого сохранения результатов генератора в списке ; это зависит от того, как вы используете генератор.

5
ответ дан 24 November 2019 в 00:00
поделиться

Вероятно, самое простое решение - обернуть дорогую часть в объект и передать ее генератору:

data = ExpensiveSetup()
for x in FunctionWithYield(data): pass
for x in FunctionWithYield(data): pass

Таким образом, вы можете кэшировать дорогостоящие вычисления.

Если вы можете сохранять все результаты в ОЗУ одновременно, затем использовать list () , чтобы материализовать результаты генератора в виде простого списка и работать с ним.

28
ответ дан 24 November 2019 в 00:00
поделиться

Генераторы не могут быть перемотаны. У вас есть следующие варианты:

  1. Снова запустить функцию генератора, перезапустив генерацию:

     y = FunctionWithYield ()
    для x в y: print (x)
    y = FunctionWithYield ()
    для x в y: print (x)
    
  2. Сохраните результаты генератора в структуре данных в памяти или на диске, которую можно повторять снова:

     y = list (FunctionWithYield ())
    для x в y: print (x)
    # можно повторить снова:
    для x в y: print (x)
    

Обратной стороной варианта 1 является повторное вычисление значений. Если это загружает процессор, вам придется рассчитывать дважды. С другой стороны, обратная сторона 2 - это хранилище. Весь список значений будет сохранен в памяти. Если имеется слишком много значений, это может быть непрактичным.

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

133
ответ дан 24 November 2019 в 00:00
поделиться

Я не уверен, что вы имели в виду под дорогой подготовкой, но я думаю, что у вас действительно есть

data = ... # Expensive computation
y = FunctionWithYield(data)
for x in y: print(x)
#here must be something to reset 'y'
# this is expensive - data = ... # Expensive computation
# y = FunctionWithYield(data)
for x in y: print(x)

Если это случае, почему бы не использовать повторно данные ?

1
ответ дан 24 November 2019 в 00:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: