Чем отличаются ключевые слова return и yield в Python

Ответ

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

return

  • Действие: Немедленно прекращает выполнение функции.
  • Результат: Возвращает одно значение или объект.
  • Состояние: Локальные переменные и состояние функции уничтожаются после вызова.
def get_list_with_return():
    # Создает и возвращает весь список сразу, занимая память
    result = []
    for i in range(3):
        result.append(i)
    return result

my_list = get_list_with_return()
# my_list -> [0, 1, 2]

yield

  • Действие: Приостанавливает выполнение, "отдавая" значение.
  • Результат: Функция становится генератором, возвращающим итератор.
  • Состояние: Состояние (включая локальные переменные) сохраняется между вызовами.
def generate_numbers_with_yield():
    # Отдает значения по одному, не храня все в памяти
    print("Генератор начал работу")
    for i in range(3):
        print(f"...yield {i}")
        yield i
    print("Генератор завершил работу")

# Использование генератора
gen = generate_numbers_with_yield()
print(next(gen)) # Выполнит код до первого yield
print(next(gen)) # Возобновит работу с места остановки

# Вывод:
# Генератор начал работу
# ...yield 0
# 0
# ...yield 1
# 1

Сравнительная таблица

Аспект return yield
Тип функции Обычная функция Генератор
Поток выполнения Завершается Приостанавливается
Количество возвратов Один раз Многократно
Эффективность памяти Может быть низкой (если возвращается большая коллекция) Высокая (ленивые вычисления)
Основное применение Возврат конечного результата вычислений Создание итераторов, обработка больших потоков данных

Ответ 18+ 🔞

Смотри, объясняю на пальцах, чтобы даже твоя бабка, если она вдруг за Python взялась, всё поняла. Всё крутится вокруг одной простой хуйни: return — это как выстрелить и сдохнуть, а yield — это как стрелять очередь, но между патронами присесть перекурить и состояние сохранить.

return — это пиздец, конец истории. Вызвали функцию — она там пошаманила, накопила в кучу какой-то результат и — бац! — return. Всё, кина не будет. Функция отдала значение и навсегда забыла, кто она такая и что с ней было. Все её локальные переменные — в утиль. Хочешь ещё раз? Зови функцию заново, пусть с нуля всё начинает.

def make_list_na_polku():
    # Создаёт сразу весь список, жрёт память, как свинья
    lst = []
    for i in range(3):
        lst.append(i)
    return lst  # Вот он, выстрел! Отдал список и сдох.

my_list = make_list_na_polku()  # my_list -> [0, 1, 2]

yield — это хитрая жопа, генератор. А вот это уже интереснее. Сказал yield — и функция не умерла, а приостановилась, как будто в коме. Она тебе отдала значение, но запомнила, на каком месте остановилась и все свои переменные. Потом ты её пинаешь — next() — и она просыпается, продолжает ровно с того же места, пока не наткнётся на следующий yield или пока не кончится совсем.

def generate_lazivo():
    print("Генератор проснулся, блядь")
    for i in range(3):
        print(f"...сейчас отдам {i}, потом усну")
        yield i  # Отдал значение и заснул до следующего пинка
    print("Всё, я кончил, пиздец.")

# Используем
gen = generate_lazivo()
print(next(gen)) # Пнули раз. Он проснулся, отдал 0, уснул.
print(next(gen)) # Пнули два. Проснулся, отдал 1, уснул.

# Вывод:
# Генератор проснулся, блядь
# ...сейчас отдам 0, потом усну
# 0
# ...сейчас отдам 1, потом усну
# 1

Короче, таблица, чтобы в глаза не ебать

Что сравниваем return yield
Что делает функция Обычная Превращается в генератор, манда с ушами
Что происходит Завершается нахуй Приостанавливается, как будто в ступоре
Сколько раз отдаёт Один, и пизда Столько, сколько захочешь, по одному значению
Память Может сожрать овердохуища, если список большой Экономит, потому что не хранит всё сразу, а генерит на ходу
Зачем нужно Когда нужен готовый результат Когда данных дохуя, или нужно лениво их отдавать, или делать бесконечные потоки