Как использовать «yield» в Python?

Как использовать «yield» в Python?

Генератор Python — от базового до расширенного использования

Если вы разработчик Python, я считаю, что вы должны знать Генератор на Python. Ключом к определению генератора Python является использование ключевого слова yield. Генератор Python повсеместно используется в сценариях, когда нам нужна большая коллекция, улучшается читаемость нашего кода и в других определенных сценариях, таких как многопоточность.

Возможно, вы еще не знаете, как правильно использовать ключевое слово «yield». В этой статье я расскажу о базовом использовании генератора Python. Некоторые более сложные шаблоны использования также будут рассмотрены в следующих разделах.

1. Основы

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

names = ['Alice', 'Bob', 'Chris', 'David', 'Emily']

Теперь мы хотим определить генератор Python из этого списка имен. Код будет следующим.

def gen_roster(names):
    for name in names:
        yield name

Обратите внимание, что нам нужно использовать ключевое слово yield, а не return, поэтому мы можем использовать эту функцию для создания генератора.

roster = gen_roster(names)

Да это оно. Если вы хотите проверить тип переменной roster, вот результат.

Теперь у нас есть roster. Генератор Python также является итеративным, поэтому мы можем поместить его в цикл for, чтобы получить все имена за один раз.

for name in roster:
    print(name)

2. Получите следующее

Хорошо, не имеет особого смысла использовать генератор в цикле for в предыдущем примере. Преимущество использования генератора заключается в том, что мы можем получить одно значение за один раз. Это может быть очень полезно, когда мы имеем дело с огромной коллекцией. То есть, когда мы создаем генератор, элементы не будут считываться в память. Этот элемент создается только в том случае, если мы пытаемся получить следующий элемент и нажимаем ключевое слово yield.

Поэтому непременно важно получить «следующий» элемент генератора. В этом случае мы можем использовать его __next__() функцию.

roster.__next__()

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

next(roster)

Вы заметили, что «курсор» перемещался, когда мы пытались получить «следующий» элемент? Помните, мы определили цикл for внутри определения генератора? Мы можем считать, что цикл for будет выполняться один раз, пока не достигнет ключевого слова yield.

Это также означает, что в данный момент наш «курсор» находится на третьем имени. Итак, если мы попытаемся вывести все остальные элементы, «Алиса» и «Боб» будут пропущены.

См. также:  Code With Me - никогда больше не покидайте свой чердак

Теперь «курсор» в конце. Если мы попытаемся получить следующий элемент, будет выдана ошибка, потому что элемента больше нет.

На самом деле это не то, что мы хотим, потому что список будет использоваться, чтобы решить, кто дежурит для текущей ротации. Другими словами, мы хотим, чтобы «курсор» вернулся в начало, чтобы все имена снова были зациклены.

Хитрость заключается в том, чтобы просто поместить оператор while True над циклом for. Итак, как только все имена будут использованы, цикл for начнется заново.

def gen_roster(names):
    while True:
        for name in names:
            yield name

Теперь предположим, что мы хотим получить список из 12 имен. У нас всего 5 сотрудников. Итак, они будут вращаться.

for i in range(12):
    print(next(roster))

Если мы не укажем число «12», генератор сможет генерировать новые имена бесконечно.

3. Отправьте значение

Одним из дополнительных способов использования генератора является отправка значения генератору. Это значение станет результатом выражения current yield, а метод вернет значение next, полученное генератором.

Итак, не ждите, что генератор вернет только что отправленное значение, потому что он вернет следующее. Однако мы можем использовать это, чтобы что-то делать внутри генератора. Например, мы можем остановить бесконечный генератор, отправив в него определенное значение.

def gen_roster(names):
    while names:
        for name in names:
            current_name = yield name
            if current_name == 'stop':
                names = None
                break

Генератор был определен для завершения цикла, если извне будет отправлено значение «стоп». Итак, мы можем проверить поведение следующим образом.

roster = gen_roster(names)
for i in range(10):
    if i == 3:
        roster.send('stop')
    print(next(roster))

В приведенном выше коде мы просим программу выполнить цикл 10 раз. Однако для 4-го раунда мы передаем в генератор значение «стоп». В результате было выведено только 3 имени, и генератор остановился на 4-м раунде, а не зацикливался 10 раз.

См. также:  Git запустился ?

Метод send будет очень полезен, когда мы хотим изменить поведение или правила генератора в сценарии многопоточного программирования.

4. Остановить генератор — выбросить исключение и закрыть

Когда что-то не так, мы можем использовать метод throw(), чтобы вызвать исключение в точке, где генератор был приостановлен. Мы можем настроить тип ошибки. В демонстрационных целях в этом руководстве я просто для удобства буду использовать TypeError.

roster = gen_roster(names)
next_name = roster.throw(TypeError, 'Stop!')

Если ничего не пошло не так, но мы все еще хотим завершить работу генератора, мы можем использовать close() метод генератора. Это было бы очень полезно, когда у нас есть бесконечный генератор, и мы хотим остановить его в определенный момент.

roster = gen_roster(names)
for i in range(10):
    if i == 3:
        roster.close()
    print(next(roster))

Приведенный выше код закрыл «список» генератора на 4-м раунде, поэтому, когда следующий цикл пытался получить следующее значение, было сгенерировано исключение.

Резюме

В этой статье я представил одну из самых важных и «питонических» концепций в Python — генератор. Использование ключевого слова yield является ключом к генератору Python.

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

Если вы считаете, что мои статьи полезны, рассмотрите возможность присоединения к Medium Membership, чтобы поддержать меня и тысячи других авторов! ‹- Нажмите

Понравилась статья? Поделиться с друзьями:
IT Шеф
Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: