Return в Python: функция возвращает результат
print показывает значение человеку, return отдаёт программе. Учимся возвращать результат, класть его в переменную и использовать в выражениях — и не путать return с print.
Редакция Питоники
Функции из первых двух уроков печатают: print_line рисует линию, greet здоровается. Печать видит человек, но программа из неё ничего не достанет: нельзя сложить два напечатанных числа, положить напечатанный список в переменную, передать дальше. Для отдачи значения программе у функции есть return — оператор возврата. Это граница между функциями-инструкциями для глаз и функциями-вычислителями для программы.
Функция, которая только печатает
Посмотрим, что на самом деле отдаёт функция с print, если её результат попробовать сохранить:
def show_total(prices):
print(sum(prices))
show_total([100, 200, 50])
result = show_total([100, 200, 50])
print(result)
350 350 None
Первая строка вывода — работа print внутри функции. Вторая — тот же print при втором вызове, результат которого мы положили в переменную result. Третья — и вот что лежит в result: None. Функция напечатала сумму, но вернула ничего: без return функция отдаёт None — специальное значение «ничего».
# Так не запускается: функция вернула None, а None умножать нельзя
def show_total(prices):
print(sum(prices))
result = show_total([10, 20])
result = result * 2
return: функция отдаёт значение
Заменим print на return — и результат станет программным:
def total(prices):
return sum(prices)
result = total([100, 200, 50])
print(result)
print(result * 2)
350 700
print показывает значение человеку, а return отдаёт значение программе. Значение вернулось из функции, легло в переменную result — и с ним можно работать: умножать, складывать, передавать в другие функции. Функция с return становится деталью конструктора: результат одной — вход для следующей.
| print внутри функции | return | |
|---|---|---|
| Кому адресовано | Человеку на экране | Программе |
| Что можно с результатом | Только посмотреть | Присвоить, посчитать, передать дальше |
| Что вернёт вызов | None | Указанное значение |
| Типичная роль | Отчёты и сообщения | Вычисления и обработка данных |
Вернувшееся значение участвует в выражениях прямо на месте вызова — переменная даже не обязательна:
def rub_to_eur(rubles, rate):
return rubles / rate
print(rub_to_eur(1000, 100))
budget = rub_to_eur(5000, 100)
print('Бюджет:', budget, 'евро')
10.0 Бюджет: 50.0 евро
return завершает функцию
return не только отдаёт значение, но и немедленно заканчивает функцию. Первый сработавший return — последний шаг вызова:
def check_age(age):
if age < 18:
return 'вход запрещён'
return 'добро пожаловать'
print(check_age(15))
print(check_age(21))
вход запрещён добро пожаловать
Для age = 15 сработал первый return — функция закончилась, до второй строки return тело не дошло. Для 21 условие ложно, и отработал нижний return. Веток может быть сколько угодно, но за один вызов выполнится ровно одна.
def double(n):
return n * 2
print('эта строка не выполнится')
print(double(5))
10
print внутри double стоит после return и не выполняется никогда: return уже завершил функцию. Python не ругается на такой код — он просто честно его не запускает. Увидели строки после return в функции без условий — это мёртвый код, его стоит удалить.
return без значения: досрочный выход
return можно написать и без значения — тогда вернётся None, но функция всё равно завершится на месте. Так делают досрочный выход: дальше по данным идти бессмысленно:
def log_out(msg):
if msg == 'стоп':
return
print('лог:', msg)
log_out('работаю')
log_out('стоп')
log_out('заканчиваю')
лог: работаю лог: заканчиваю
Сообщение «стоп» прервало функцию до печати: второй вызов не оставил следа в логе. Без if такой стоп не сделать — return посреди тела завершил бы функцию всегда, и лог печатал бы только первую строку.
Собираем: функция-вычислитель в работе
Финальный пример: функция считает средний балл, а вызывающий код решает, что с ним делать. Считает функция, печатает и решает — программа:
def average(numbers):
return sum(numbers) / len(numbers)
scores = [4, 5, 3, 5]
avg = average(scores)
print('Средний балл:', avg)
if avg >= 4:
print('Зачёт')
else:
print('Пересдача')
Средний балл: 4.25 Зачёт
average ничего не печатает — она только возвращает число. Печать и решение о зачёте живут в вызывающем коде: такую функцию можно переиспользовать где угодно, не трогая её тело. Считать и возвращать умеет теперь и ваша функция; данные в неё попадают аргументами из урока про аргументы, а необязательные параметры с запасными значениями — следующий шаг, урок про умолчания.
Два значения из одной функции
Вопросов у данных часто два: какой товар самый дешёвый и сколько он стоит. Возвращать список из двух элементов неудобно — на вызывающей стороне непонятно, что где. Python решает это кортежем: напишите return name, price — и получите кортеж, который распаковывается в две переменные одной строкой.
def cheapest(cart):
best = cart[0]
for item in cart:
if item[1] < best[1]:
best = item
return best[0], best[1]
name, price = cheapest([('Хлеб', 240), ('Сыр', 45), ('Молоко', 80)])
print(name, price)
Сыр 45
Строка name, price = cheapest(...) — это распаковка: Python знает, что справа кортеж из двух элементов, и раскладывает их по переменным. Если элементов в кортеже больше, чем переменных слева, будет ValueError: too many values to unpack. Обратная история тоже работает: верните кортеж целиком одной переменной — и он придёт как один объект, который можно положить в список или сравнить с другим кортежем.
Ветка, которая забыла return
Самая неприятная ошибка в функциях с возвратом — не SyntaxError, а тихий None. Функция с условием, где в одной ветке есть return, а в другой забыли, выглядит вполне рабочей: читается, запускается, ошибок не даёт. Она просто в одной из веток отдаёт None вместо значения.
def discount(price, has_card):
if has_card:
return price - price // 10
return price
def discount_bad(price, has_card):
if has_card:
return price - price // 10
print(discount(500, True))
print(discount_bad(500, False))
450 None
Первый вызов вернул 450 — скидка посчитана. Второй вернул None: ветка без карты просто дошла до конца тела. Дальше по программе кто-то сложит это значение с суммой заказа — и получит TypeError про NoneType, и ошибка укажет совсем не туда, где дело вышло из-под контроля. Правило простое: если функция в одной ветке возвращает значение, в другой ветке тоже должен быть return.
Возвращать или печатать
Границу между print и return проще всего держать в голове одной таблицей. Она отвечает на вопрос «кто будет пользоваться результатом», и почти всегда ответ очевиден.
| Ситуация | Что делать | Почему так |
|---|---|---|
| Функция считает или выбирает | return значение | результат пойдёт дальше по программе |
| Функция показывает отчёт человеку | смотреть будут люди, а не программа | |
| Нужно и посчитать, и показать | return, печать — в вызывающем коде | иначе результат не достанешь |
| Хочется и то и другое в одной функции | две функции: вычислитель и принтер | одна функция — одна задача |
Мы держимся правила: вычислитель возвращает, принтер печатает. Когда в задании просят «посчитать и сразу показать», мы не ломаем правило, а заводим пару функций: одна считает, вторая печатает результат. Две маленькие функции читаются лучше одной с двойным назначением, и их легко заменить в тестах.
None — это тоже результат
Отдельная тема — как выглядит «ничего» в возвращаемом значении. Если поиск не нашёл подходящего элемента, возвращать 0 или пустую строку неправильно: ноль — это полноценное число, пустая строка — полноценный текст. Правильный ответ — None, и вызывающий код должен его учитывать.
def find_user(users, name):
for user in users:
if user['name'] == name:
return user
return None
users = [{'name': 'Аня', 'age': 24}, {'name': 'Боря', 'age': 31}]
found = find_user(users, 'Аня')
missing = find_user(users, 'Коля')
if missing is None:
print('Коля не найден')
else:
print(missing)
Коля не найден
Проверка is None, а не == None: так пишут, когда хотят точно убедиться, что значения нет. Возвращать None из функции поиска — сознательное решение, и вызывающий код обязан его ждать. Дальше эта договорённость превращается в проверки и исключения — урок про ошибки функций разбирает, как Python сообщает о том, что пошло не так.
Практика: заказ, который считает функция
Соберём вместе всё, что разобрали: функция считает и возвращает, вызывающий код печатает и принимает решение. Порядок именно такой — иначе решение пришлось бы зашивать в тело функции.
def order_total(items):
total = 0
for name, price in items:
total = total + price
return total
order = [('Хлеб', 45), ('Молоко', 80)]
total = order_total(order)
print('Заказ на', total, 'руб.')
if total > 100:
print('Доставка бесплатно')
Заказ на 125 руб. Доставка бесплатно
Функция order_total ничего не знает про доставку и про порог в 100 рублей — она просто считает. Всё остальное живёт в вызывающем коде, поэтому порог легко поменять, а саму функцию — вызвать из другого отчёта. Считать и возвращать вы теперь умеете; данные в функцию попадают аргументами из урока про аргументы, а необязательные параметры с запасными значениями — это урок про умолчания.
Сначала предскажи ответ в голове — это главный навык программиста.
def f(x):
return x * 3
y = f(4)
print(y + 1)
def f():
print('внутри')
x = f()
print(x)
def f(x):
if x > 5:
return 'большой'
return 'маленький'
print(f(3))
print(f(10))
1. Что делает return?
2. Что вернёт функция без return?
3. Функция объявлена как def f(x): return x * 3. Что окажется в y после y = f(4)?
4. Что выполнится из строк, стоящих в теле функции после сработавшего return?
5. Чем return отличается от print?
6. Сколько return выполнится за один вызов функции?
7. В функции написан только if: return 1, а после if никакого return нет. Что вернёт вызов, когда условие ложно?
8. Функция вернула кортеж из двух чисел. Как его получить в двух переменных?
9. Что вернёт функция, в которой есть и print, и return?
Напиши функцию discount(price), которая возвращает цену со скидкой десятой части: price - price // 10. Примени её к списку цен [500, 200, 1000], собери итоговую сумму через аккумулятор и напечатай строку «Итого со скидкой: ...».
Чем return отличается от print в функции?
print показывает значение человеку на экране, return отдаёт значение программе: его можно присвоить переменной, использовать в выражении, передать в другую функцию. Рабочая функция возвращает, печатает — код, который её вызвал.
Урок 2: аргументы функцииЧто вернёт функция без return?
None — специальное значение «ничего». Поэтому result = функция_с_print даёт None, а арифметика с таким результатом падает с TypeError про NoneType. Если нужен результат — пишите return значение.
Может ли в функции быть несколько return?
Да, в разных ветках условий: за один вызов сработает ровно один — первый, до которого дошло выполнение. Он же завершит функцию, поэтому код после сработавшего return не выполняется.
Как вернуть из функции два значения?
Написать их через запятую: return best, worst — Python упакует их в кортеж, и вызывающий код распакует в две переменные: b, w = функция(). Это удобная связка, когда функция отвечает сразу на два вопроса о данных.
Почему функция возвращает None, хотя я ожидал число?
Скорее всего, в одной из веток забыт return: если условие ложно, тело просто доходит до конца и функция возвращает None. Ошибка не выглядит как ошибка — она всплывёт позже, там, где с результатом попробуют посчитать. Проверьте, что в каждой ветке есть return.
Можно ли в одной функции и напечатать, и вернуть значение?
Технически да, но мы так не делаем: print адресован человеку, return — программе. Смешивание делает функцию неоднозначной — непонятно, за что её звать. Лучше две функции: одна считает и возвращает, вторая печатает результат.
Что вернёт функция, если выполнение дошло до конца тела, а return не встретился?
None. Python не выдаёт ошибку и не предупреждает — функция просто отдаёт «ничего». Именно поэтому мы пишем return в конце тела как запасной вариант или в каждой ветке: тогда результат предсказуем в любом случае.
Понравился урок? Сошлитесь на него
«print показывает значение человеку, а return отдаёт значение программе.»
Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Функции · Урок 2
Аргументы функции в Python: данные внутрь
Функция принимает данные через параметры: greet('Анна') здоровается с Анной. Разбираем позиционные аргументы, порядок и количество — и типичную ошибку TypeError.
Функции · Урок 4
Умолчания и именованные аргументы в Python
Необязательные параметры с запасными значениями и вызов по имени: def f(x, n=2) и f(x=5, n=3). Разбираем порядок параметров и знакомимся с ловушкой изменяемого умолчания.
Циклы · Урок 11
Счётчики и аккумуляторы в циклах Python
Сумма чека, число совпадений, лучший результат: переменная, объявленная до цикла и копящая значения внутри, — приём старше языков. Разбираем счётчики, суммы, максимумы и их ловушки.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
json · Урок 19
Мини-клиент API на функциях
URL, разбор ответа, фильтр, файл — каждый шаг уже умещается в одну функцию. Собираем их в клиент, который читается как сценарий.
python клиент api функциифункции python для обработки json
Множества · Урок 14
Функция возвращает несколько значений: return с кортежем
Функция возвращает пару значений одной строкой: запятая в return собирает кортеж, распаковка раскладывает его по переменным. min и max за один проход, звёздочка для остатка.
python return несколько значенийфункция возвращает кортеж python
Функции · Урок 8
filter в Python: оставить подходящие
map менял каждый элемент, а filter выбирает: оставить только чётные, только длинные слова, только заполненные строки. Разбираем filter и его хитрости.
python filter функцияfilter none python