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