Возврат значений из функции. Оператор return
Функции могут передавать какие-либо данные из своих тел в основную ветку программы. Говорят, что функция возвращает значение. В большинстве языков программирования, в том числе Python, выход из функции и передача данных в то место, откуда она была вызвана, выполняется оператором return .
Если интерпретатор Питона, выполняя тело функции, встречает return , то он «забирает» значение, указанное после этой команды, и «уходит» из функции.
def cylinder(): r = float(input()) h = float(input()) # площадь боковой поверхности цилиндра: side = 2 * 3.14 * r * h # площадь одного основания цилиндра: circle = 3.14 * r**2 # полная площадь цилиндра: full = side + 2 * circle return full square = cylinder() print(square)
3 7 188.4
В данной программе в основную ветку из функции возвращается значение локальной переменной full . Не сама переменная, а ее значение, в данном случае – какое-либо число, полученное в результате вычисления площади цилиндра.
В основной ветке программы это значение присваивается глобальной переменной square . То есть выражение square = cylinder() выполняется так:
- Вызывается функция cylinder() .
- Из нее возвращается значение.
- Это значение присваивается переменной square .
Не обязательно присваивать результат переменной, его можно сразу вывести на экран:
. print(cylinder())
Здесь число, полученное из cylinder() , непосредственно передается функции print() . Если мы в программе просто напишем cylinder() , не присвоив полученные данные переменной или не передав их куда-либо дальше, то эти данные будут потеряны. Но синтаксической ошибки не будет.
В функции может быть несколько операторов return . Однако всегда выполняется только один из них. Тот, которого первым достигнет поток выполнения. Допустим, мы решили обработать исключение, возникающее на некорректный ввод. Пусть тогда в ветке except обработчика исключений происходит выход из функции без всяких вычислений и передачи значения:
def cylinder(): try: r = float(input()) h = float(input()) except ValueError: return side = 2 * 3.14 * r * h circle = 3.14 * r**2 full = side + 2 * circle return full print(cylinder())
Если попытаться вместо цифр ввести буквы, то сработает return , вложенный в except . Он завершит выполнение функции, так что все нижеследующие вычисления, в том числе return full , будут опущены. Пример выполнения:
r None
Но постойте! Что это за слово None , которое нам вернул «пустой» return ? Это ничего, такой объект – «ничто». Он принадлежит классу NoneType . До этого мы знали четыре типа данных, они же четыре класса: int , float , str , bool . Пришло время пятого.
Когда после return ничего не указывается, то по умолчанию считается, что там стоит объект None . При желании мы можете явно писать return None .
Более того. Ранее мы рассматривали функции, которые вроде бы не возвращали никакого значения, потому что в них не было оператора return . На самом деле возвращали, просто мы не обращали на него внимание, не присваивали никакой переменной и не выводили на экран. В Python всякая функция что-либо возвращает. Если в ней нет оператора return , то она возвращает None . То же самое, как если в ней имеется «пустой» return .
Возврат нескольких значений
В Питоне позволительно возвращать из функции несколько объектов, перечислив их через запятую после команды return :
def cylinder(): r = float(input()) h = float(input()) side = 2 * 3.14 * r * h circle = 3.14 * r ** 2 full = side + 2 * circle return side, full s_cyl, f_cyl = cylinder() print("Площадь боковой поверхности %.2f" % s_cyl) print("Полная площадь %.2f" % f_cyl)
Из функции cylinder() возвращаются два значения. Первое из них присваивается переменной s_cyl , второе – f_cyl . Возможность такого группового присвоения – особенность Python, обычно не характерная для других языков:
>>> a, b, c = 10, 15, 19 >>> a 10 >>> b 15 >>> c 19
Фокус здесь в том, что перечисление значений через запятую (например, 10, 15, 19 ) создает объект типа tuple . На русский переводится как «кортеж». Это разновидность структур данных, которые будут изучены позже.
Когда же кортеж присваивается сразу нескольким переменным, то происходит сопоставление его элементов соответствующим в очереди переменным. Это называется распаковкой.
Таким образом, когда из функции возвращается несколько значений, на самом деле из нее возвращается один объект класса tuple . Перед возвратом эти несколько значений упаковываются в кортеж. Если же после оператора return стоит только одна переменная или объект, то ее/его тип сохраняется как есть.
Распаковка не является обязательной. Будет работать и так:
… print(cylinder())
4 3 (75.36, 175.84)
На экран выводится кортеж, о чем говорят круглые скобки. Его также можно присвоить одной переменной, а потом вывести ее значение на экран.
Практическая работа
- Напишите программу, в которой вызывается функция, запрашивающая с ввода две строки и возвращающая в программу результат их конкатенации. Выведите результат на экран.
- Напишите функцию, которая считывает с клавиатуры числа и перемножает их до тех пор, пока не будет введен 0. Функция должна возвращать полученное произведение. Вызовите функцию и выведите на экран результат ее работы.
Примеры решения и дополнительные уроки в pdf-версии курса
X Скрыть Наверх
Python. Введение в программирование
Почему функция выводит none в Python?
Достаточно часто возникают вопросы: «почему моя функция ничего не возвращает?!», «почему из функции возвращается None?», «не могу понять откуда появляется None. «.
Для начала необходимо понимать и помнить, что любая функция в Python всегда что-то возвращает и если не используется оператор return для возврата значения (такие случаи бывают, но об этом позднее), то функция возвращает объект None . В случае если return используется, но после него ничего не указывается явно, то по умолчанию считается, что там стоит объект None .
# Не используем оператор return, поэтому результат не возвращается. def func(x): x * x print(func(10)) #=> None # Используем оператор return, но не задаем явное значение/используем некорректно def func(x): x * x return print(func(10)) #=> None # Корректно возвращаем результат с использованием оператора return def func(x): return x * x print(func(10)) #=> 100
Порой бывает, что по ошибке указывается возврат вместе с функцией print() . Для информации функция print() в Python выводит переданные аргументы на стандартное устройство вывода (экран), но при этом не возвращает значений, т.е. можно считать, что возвращает None .
def func(x): return print(x * x) a = 5 b = func(a) # Присваиваем результат функции переменной b # Результат работы функции выводится на экран, благодаря print() в теле функции. #=> 25 # Но при этом данный результат не присваивается переменной b. print(b) #=> None
Если дальше по коду проводятся манипуляции с переменной b, например сложение, то возникнет ошибка TypeError :
c = b + 1 # Пытаемся сложить None и 1 print(c) # => TypeError: unsupported operand type(s) for +: 'NoneType' and 'int'
Возможен вариант, когда функция и не должна ничего возвращать, она производит какие-либо действия с объектами в глобальной зоне видимости и на этом ее функционал заканчивается. В таком случае return может и не использоваться, но необходимо помнить, что в этом случае функция возвращает None .
# Бесполезная функция необходимая только в качестве примера. def extend_list(list1, list2): list1.extend(list2) list1 = [1, 2] list2 = [3, 4] print(extend_list(list1, list2)) # => None # При этом поставленную задачу функция выполнила - изменила list1 print(list1) # => [1, 2, 3, 4]
В примере выше использовался метод работы со списками extend() и необходимо понимать, что метод изменяет объект, к которому применен, а не возвращает результат изменения объекта.
list3 = extend_list(list1, list2) print(list3) # => None
Python: Возврат значений
В этом уроке подробнее разберем, как работать с созданными функциями, чтобы они были полезны.
Когда мы определяем функцию, она печатает на экран какие-то данные:
def greeting(): print('Hello, Hexlet!')
Пользы от таких функций немного, так как результатом нельзя воспользоваться внутри программы. Рассмотрим на примере.
Возьмем задачу обработки электронной почты. Когда пользователь регистрируется на сайте, то он может ввести email любым способом:
- Добавить случайно пробелы в начале или в конце: _support@hexlet.io__
- Использовать буквы в разном регистре: SUPPORT@hexlet.io
Если мы сохраним его в таком виде в базу данных, то пользователь не войдет на сайт. Чтобы этого не произошло, email нужно подготовить к записи в базу: привести его к нижнему регистру и обрезать пробелы по краям строки. Такая задача решается в пару строчек:
def save_email(): # Email приходит из формы email = ' SuppORT@hexlet.IO' # Обрезаем пробельные символы trimmed_email = email.strip() prepared_email = trimmed_email.lower() print(prepared_email) # Здесь будет запись в базу данных
Этот код стал возможен благодаря тому, что значение вернулось. Методы strip() и lower() ничего не печатают на экран, они возвращают результат своей работы. Поэтому мы можем записать его в переменные. Если бы они печатали на экран, мы бы не могли присвоить результат переменной. Например, так мы не можем сделать с функцией greeting() :
message = greeting() # в действительности, функция print() возвращает None # None — специальный объект, используемый для представления отсутствия значения print(message) # => None
Теперь изменим функцию greeting() так, чтобы она возвращала данные. Для этого выполним возврат вместо печати на экран:
def greeting(): return 'Hello, Hexlet!'
return — это инструкция. Она берет записанное справа выражение и отдает его тому коду, который вызвал метод. Здесь выполнение функции завершается.
# Теперь мы можем использовать результат работы функции message = greeting() print(message) # => Hello, Hexlet! # И даже выполнить какие-то действия над результатом print(message.upper()) # => HELLO, HEXLET!
Любой код после return не выполняется:
def greeting_with_code_after_return(): return 'Hello, Hexlet!' print('Я никогда не выполнюсь')
Даже если функция возвращает данные, это не ограничивает ее в том, что она печатает. Кроме возврата данных мы можем и печатать:
def greeting_with_return_and_printing(): print('Я появлюсь в консоли') return 'Hello, Hexlet!' # И напечатает текст на экран, и вернет значение message = greeting_with_return_and_printing()
Возвращать можно не только конкретное значение. Так как return работает с выражениями, то справа от него может быть что угодно. Здесь нужно руководствоваться принципами читаемости кода:
def greeting(): message = 'Hello, Hexlet!' return message
Здесь мы не возвращаем переменную. Возвращается всегда значение, которое находится в этой переменной. Ниже пример с вычислениями:
def double_five(): # или return 5 + 5 result = 5 + 5 return result
Определить функцию мало. Еще важно, чтобы она была полезна, и результатом можно было воспользоваться. А теперь подумайте, что вернет вызов, определенной ниже функции run() ?
# Определение def run(): return 5 return 10 # Что будет выведено на экран? print(run())
Задание
Реализуйте функцию say_hurray_three_times() , которая возвращает строку ‘hurray! hurray! hurray!’.
hurray = say_hurray_three_times() print(hurray) # => hurray! hurray! hurray!
Упражнение не проходит проверку — что делать?
Если вы зашли в тупик, то самое время задать вопрос в «Обсуждениях». Как правильно задать вопрос:
- Обязательно приложите вывод тестов, без него практически невозможно понять что не так, даже если вы покажете свой код. Программисты плохо исполняют код в голове, но по полученной ошибке почти всегда понятно, куда смотреть.
В моей среде код работает, а здесь нет
Тесты устроены таким образом, что они проверяют решение разными способами и на разных данных. Часто решение работает с одними входными данными, но не работает с другими. Чтобы разобраться с этим моментом, изучите вкладку «Тесты» и внимательно посмотрите на вывод ошибок, в котором есть подсказки.
Мой код отличается от решения учителя
Это нормально , в программировании одну задачу можно выполнить множеством способов. Если ваш код прошел проверку, то он соответствует условиям задачи.
В редких случаях бывает, что решение подогнано под тесты, но это видно сразу.
Прочитал урок — ничего не понятно
Создавать обучающие материалы, понятные для всех без исключения, довольно сложно. Мы очень стараемся, но всегда есть что улучшать. Если вы встретили материал, который вам непонятен, опишите проблему в «Обсуждениях». Идеально, если вы сформулируете непонятные моменты в виде вопросов. Обычно нам нужно несколько дней для внесения правок.
Кстати, вы тоже можете участвовать в улучшении курсов: внизу есть ссылка на исходный код уроков, который можно править прямо из браузера.
Почему функция возвращает None?
Доброго времени суток. Решил начать самообучаться азам Python. Сейчас играюсь с функциями и return. Написал вот такой калькулятор, но он возвращает None, хотя весь код исполняется.
Подскажите, пожалуйста, в чем я ошибаюсь. Самостоятельный поиск в гугле не помог.
#Вычисляем факториал def factorial(num1): if num1 == 1: return 1 elif num1 > 0: return num1 * factorial (num1 - 1) else: return ('Не верное число') #Вычисляем сумму def summa(num1, num2): return (num1 + num2) #Вычисляем разность def raznost(num1, num2): return (num1 - num2) #Вычисляем произведение def proisvedenie(num1, num2): return (num1 * num2) #Вычисляем деление def delenie(num1, num2): if num2 == 0: return ('Делить на 0 нельзя') else: return (num1 / num2) #Определяем что делать def deistvie(znak, num1, num2): if znak == '!': factorial(num1) elif znak == '+': summa(num1, num2) elif znak == '-': raznost(num1, num2) elif znak == '*': proisvedenie(num1, num2) elif znak == '/': delenie(num1, num2) else: return ('Нет такого действия') #Получаем данные def inputs(): num1 = float(input('Введите число: ')) znak = input('Введите знак (+, -, *, /, !): ') if znak == '!': num2 = '' else: num2 = float(input('Введите второе число: ')) deistvie (znak, num1, num2) print (inputs())
- Вопрос задан более трёх лет назад
- 6901 просмотр
Комментировать
Решения вопроса 1
В вашей функции deistvie происходит просто вызов функций сложение, вычитания, умножения и т.д. И вы с ними ничего не делатете, т.е. как вариант, это выводить результат, например так:
#Определяем что делать def deistvie(znak, num1, num2): if znak == '!': print(factorial(num1)) elif znak == '+': print(summa(num1, num2)) elif znak == '-': print(raznost(num1, num2)) elif znak == '*': print(proisvedenie(num1, num2)) elif znak == '/': print(delenie(num1, num2)) else: return ('Нет такого действия')
либо надо возвращать значения в deistvie и в inputs, т.е. таким образом
#Определяем что делать def deistvie(znak, num1, num2): if znak == '!': return factorial(num1) elif znak == '+': return summa(num1, num2) elif znak == '-': return raznost(num1, num2) elif znak == '*': return proisvedenie(num1, num2) elif znak == '/': return delenie(num1, num2) else: return ('Нет такого действия') #Получаем данные def inputs(): num1 = float(input('Введите число: ')) znak = input('Введите знак (+, -, *, /, !): ') if znak == '!': num2 = '' else: num2 = float(input('Введите второе число: ')) return deistvie (znak, num1, num2)