Как клонировать объект генератора Python?

Рассмотрим этот сценарий:

  #! / usr / bin / env python
 # - * - кодирование: utf-8 - * -
 import os

 walk = os.walk ('/ home')

 для root, dirs, файлов в пути:
     для имени пути в файлах dirs +:
         print os.path.join (root, pathname)

 для root, dirs, файлов в пути:
     для имени пути в файлах dirs +:
         print os.path.join (root, pathname) 

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

Я пробовал walk2 = walk к клону и использовать на второй итерации, но это не сработало. Вопрос … Как я могу его скопировать? Возможно ли это?

Заранее спасибо.

4 Solutions collect form web for “Как клонировать объект генератора Python?”

Вы можете использовать itertools.tee() :

 walk, walk2 = itertools.tee(walk) 

Обратите внимание, что это может «потребовать значительного дополнительного хранения», как указано в документации.

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

walk = list(os.walk('/home'))

Определить функцию

  def walk_home(): for r in os.walk('/home'): yield r 

Или даже это

 def walk_home(): return os.walk('/home') 

Оба используются следующим образом:

 for root, dirs, files in walk_home(): for pathname in dirs+files: print os.path.join(root, pathname) 

Этот ответ направлен на расширение / уточнение того, что высказали другие ответы. Решение обязательно будет зависеть от того , чего именно вы стремитесь достичь.

Если вы хотите os.walk один и тот же результат os.walk несколько раз, вам нужно будет инициализировать список из os.walk os.walk iterable (т. os.walk Walk walk = list(os.walk(path)) ).

Если вы должны гарантировать, что данные остаются теми же, это, вероятно, ваш единственный вариант. Однако существует несколько сценариев, в которых это невозможно или желательно.

  1. Невозможно list() итерабельность, если выход имеет достаточный размер (т. Е. Попытка list() вся файловая система может заморозить ваш компьютер).
  2. Нежелательно list() итерируемый, если вы хотите получить «свежие» данные перед каждым использованием.

Если list() не подходит, вам нужно будет запустить генератор по требованию. Обратите внимание, что генераторы гасятся после каждого использования, поэтому это создает небольшую проблему. Чтобы «повторно запустить» ваш генератор несколько раз, вы можете использовать следующий шаблон:

 #!/usr/bin/env python # -*- coding: utf-8 -*- import os class WalkMaker: def __init__(self, path): self.path = path def __iter__(self): for root, dirs, files in os.walk(self.path): for pathname in dirs + files: yield os.path.join(root, pathname) walk = WalkMaker('/home') for path in walk: pass # do something... for path in walk: pass 

Вышеупомянутый шаблон дизайна позволит вам сохранить код DRY.

  • Есть ли способ проверить, содержат ли два объекта одинаковые значения в каждой из своих переменных в python?
  • Словарь Python из полей объекта
  • class Classname (object), какое слово является «объектом» в Python?
  • Почему или скорее, как объект .__ new__ работает по-разному в этих двух случаях
  • В Python, какой оператор переопределить для «if object:»?
  • Каков самый общий тип python, к которому я могу добавить атрибуты?
  • Понимание объектов в Python
  • Добавление атрибутов в объекты python
  • Python - лучший язык программирования в мире.