2016-04-19 2 views
8

Когда вы создаете экземпляр функции генератора, он не будет выполнять какой-либо код, пока вы не назовете на него next.Продвинутая функция генератора Python перед первым выходом

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

Рассмотрим следующий пример:

def generator(filename): 
    with open(filename) as f: 
     data = f.read() 

    while True: 
     yield data 

gen = generator('/tmp/some_file') 
# at this point, no generator code is executed 

# initialization code is executed only at the first iteration 
for x in gen: 
    pass 

Если файл не существует, то будет сгенерировано исключение на цикл. Я бы , как и код до первого yield для выполнения до того, как генератор будет итерирован, поэтому любые исключения во время инициализации будут подняты при создании экземпляра генератора.

Есть ли чистый питонический способ сделать это?

+0

@ TadhgMcDonald-Jensen: Ничего себе, никто не опубликовал решение «отдельная функция инициализации» в течение трех лет. Принятый ответ на этот вопрос работает, но он заставляет вас разобраться со всеми неприятностями написания вашего итератора в качестве конечного автомата, который генераторы должны были сэкономить. – user2357112

+0

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

+0

лично я обнаружил, что ['primed' function solution] (http://stackoverflow.com/a/5725046/5827215) был тем, кого я искал, когда я впервые нашел этот вопрос, хотя я его немного модифицировал, чтобы украсить функция вместо вызова с итератором. –

ответ

5

Wrap регулярная функция вокруг генератора и поставить инициализацию там: (. В этом случае, вы могли бы заменить внутренний генератор с itertools.repeat, но не в целом)

def file_contents_repeated(filename): 
    with open(filename) as f: 
     data = f.read() 
    return _gen(data) 

def _gen(data): 
    while True: 
     yield data 

2

Функция оберточное решение отлично работает. Если вы хотите сохранить весь код в той же функции, вы можете создать закрытие.

def generator(filename): 
    with open(filename) as f: 
     data = f.read() 

    def _generator(): 
     while True: 
      yield data 

    return _generator() 
Смежные вопросы