что значит вернуть переменную
Возвращаемые значения функций
Для нас в этом курсе имеется ещё один важный момент. Посмотрим внимательнее на возвращаемое значение функций. Некоторые функции не возвращают существенное значение после завершения, но некоторые возвращают, и важно понимать что это за значение и как использовать его в своём коде и как сделать так чтобы ваши собственные функции возвращали полезные значения. Мы объясним всё это ниже.
Необходимые навыки: | |
---|---|
Цели: | Понять что такое возвращаемое значение функции и как его использовать. |
Что из себя представляют возвращаемые значения?
Если вы посмотрите на функцию replace() на MDN reference page, вы увидите секцию под названием Return value. Очень важно знать и понимать какие значения возвращаются функциями, так что мы пытаемся включать эту информацию везде, где это возможно.
Некоторые функции не возвращают значения( на наших reference pages, возвращаемое значение обозначено как void или undefined в таких случаях). Например, в функции displayMessage() которую мы сделали в прошлой статье, в результате выполнения функции не возвращается никакого значения. Функция всего лишь отображает что-то где-то на экране.
В основном, возвращаемое значение используется там, где функция является чем-то вроде вспомогательного звена при вычислениях. Вы хотите получить результат, который включает в себя некоторые значения. Эти значения вычисляются функцией, которая возвращает результат так, что он может быть использован в следующих стадиях вычисления.
Использование возвращаемых значений в ваших собственных функциях
Тоже самое может быть написано вот так:
Но первую версию написать быстрее и она более компактна.
Мы возвращаем результат вычисления Math.floor(Math.random()*number) каждый раз когда функция вызывается. Это возвращаемое значение появляется в момент вызова функции и код продолжается. Так, например, если мы выполним следующую строчку:
и 3 вызова random() вернут значения 500, 200 и 35, соответственно, строчка будет выполнена как если бы она была такой:
Активное обучение: наша собственная, возвращающая значение функция
Теперь напишем нашу собственную возвращающую значение функцию.
Почему функция «возвращает» значение?
Изучающие программирование часто удивляются: почему функция «возвращает» результат? Почему именно такое странное слово — «возврат»? Как будто мы сначала даём ей результат, а потом она его возвращает обратно.
Понятно, что это не так. Мы даём функции аргументы (а иногда и вообще не даём ничего), а она даёт нам в ответ какую-то информацию… А иногда не даёт! Тогда мы говорим «она ничего не возвратила».
Дело в том, что return означает не возврат информации, а возврат управления.
При вызове функции текущий код становится на паузу и передаёт управление в функцию. Функция делает свои дела и возвращает управление в то место, где происходил вызов. И заодно может отправить какую-то информацию туда.
Что за управление? Управление той штукой, которая исполняет код. Грубо говоря — управление компьютером. Код передаёт функции пульт управления компьютером, а функция потом возвращает его обратно.
Мы привыкли читать подобный код как «функция возвращает значение answer », но правильнее будет читать «функция возвращает управление в место вызова и отправляет туда значение answer».
Именно поэтому внутри функции возможен такой код:
Здесь функция не «возвращает ничего», а «возвращает управление в место вызова и не отправляет туда никакую информацию».
Конечно, такая формулировка хоть и технически более корректна, в реальной жизни нет смысла отказываться от «возвращает значение». Это, можно сказать, общепринятое сокращение.
Полезная информация Начните изучать разработку с бесплатного курса «Основы современной вёрстки». Вы научитесь создавать статические веб-страницы, стилизовать элементы, использовать редакторы кода с полезными расширениями. В конце курса вы опубликуете свой первый сайт на GitHub Pages.
С нуля до разработчика. Возвращаем деньги, если не удалось найти работу.
Урок №100. Возврат значений по ссылке, по адресу и по значению
Обновл. 13 Сен 2021 |
На трех предыдущих уроках мы узнали о передаче аргументов в функции по значению, по ссылке и по адресу. На этом уроке мы рассмотрим возврат значений обратно из функции в вызывающий объект всеми этими тремя способами.
Возврат значений (с помощью оператора return) работает почти так же, как и передача значений в функцию. Все те же плюсы и минусы. Основное отличие состоит в том, что поток данных двигается уже в противоположную сторону. Однако здесь есть еще один нюанс — локальные переменные, которые выходят из области видимости и уничтожаются, когда функция завершает свое выполнение.
Возврат по значению
Возврат по значению — это самый простой и безопасный тип возврата. При возврате по значению, копия возвращаемого значения передается обратно в caller. Как и в случае с передачей по значению, вы можете возвращать литералы (например, 7 ), переменные (например, x ) или выражения (например, x + 2 ), что делает этот способ очень гибким.
Еще одним преимуществом является то, что вы можете возвращать переменные (или выражения), в вычислении которых задействованы и локальные переменные, объявленные в теле самой функции. При этом, можно не беспокоиться о проблемах, которые могут возникнуть с областью видимости. Поскольку переменные вычисляются до того, как функция производит возврат значения, то здесь не должно быть никаких проблем с областью видимости этих переменных, когда заканчивается блок, в котором они объявлены. Например:
Возврат по значению идеально подходит для возврата переменных, которые были объявлены внутри функции, или для возврата аргументов функции, которые были переданы по значению. Однако, подобно передаче по значению, возврат по значению медленный при работе со структурами и классами.
Когда использовать возврат по значению:
при возврате переменных, которые были объявлены внутри функции;
при возврате аргументов функции, которые были переданы в функцию по значению.
Когда не использовать возврат по значению:
при возврате больших структур или классов (используйте возврат по ссылке).
Возврат по адресу
Возврат по адресу — это возврат адреса переменной обратно в caller. Подобно передаче по адресу, возврат по адресу может возвращать только адрес переменной. Литералы и выражения возвращать нельзя, так как они не имеют адресов. Поскольку при возврате по адресу просто копируется адрес из функции в caller, то этот процесс также очень быстрый.
Тем не менее, этот способ имеет один недостаток, который отсутствует при возврате по значению: если вы попытаетесь возвратить адрес локальной переменной, то получите неожиданные результаты. Например:
Как вы можете видеть, value уничтожается сразу после того, как её адрес возвращается в caller. Конечным результатом будет то, что caller получит адрес освобожденной памяти (висячий указатель), что, несомненно, вызовет проблемы. Это одна из самых распространенных ошибок, которую делают новички. Большинство современных компиляторов выдадут предупреждение (а не ошибку), если программист попытается вернуть локальную переменную по адресу. Однако есть несколько способов обмануть компилятор, чтобы сделать что-то «плохое», не генерируя при этом предупреждения, поэтому вся ответственность лежит на программисте, который должен гарантировать, что возвращаемый адрес будет корректен.
Возврат по адресу часто используется для возврата динамически выделенной памяти обратно в caller:
Здесь не возникнет никаких проблем, так как динамически выделенная память не выходит из области видимости в конце блока, в котором объявлена, и все еще будет существовать, когда адрес будет возвращаться в caller.
Когда использовать возврат по адресу:
при возврате динамически выделенной памяти;
при возврате аргументов функции, которые были переданы по адресу.
Когда не использовать возврат по адресу:
при возврате переменных, которые были объявлены внутри функции (используйте возврат по значению);
при возврате большой структуры или класса, который был передан по ссылке (используйте возврат по ссылке).
Возврат по ссылке
Подобно передаче по ссылке, значения, возвращаемые по ссылке, должны быть переменными (вы не сможете вернуть ссылку на литерал или выражение). При возврате по ссылке в caller возвращается ссылка на переменную. Затем caller может её использовать для продолжения изменения переменной, что может быть иногда полезно. Этот способ также очень быстрый и при возврате больших структур или классов.
Однако, как и при возврате по адресу, вы не должны возвращать локальные переменные по ссылке. Рассмотрим следующий фрагмент кода:
Возврат по ссылке обычно используется для возврата аргументов, переданных в функцию по ссылке. В следующем примере мы возвращаем (по ссылке) элемент массива, который был передан в функцию по ссылке:
Результат выполнения программы:
Хотя этот пример непрактичен, так как мы можем напрямую обратиться к 15 элементу массива, но как только мы будем рассматривать классы, то вы обнаружите гораздо больше применений для возврата значений по ссылке.
Когда использовать возврат по ссылке:
при возврате ссылки-параметра;
при возврате элемента массива, который был передан в функцию;
при возврате большой структуры или класса, который не уничтожается в конце функции (например, тот, который был передан в функцию).
Когда не использовать возврат по ссылке:
при возврате переменных, которые были объявлены внутри функции (используйте возврат по значению);
при возврате стандартного массива или значения указателя (используйте возврат по адресу).
Смешивание возвращаемых значений и ссылок
Хотя функция может возвращать как значение, так и ссылку, caller может неправильно это интерпретировать. Посмотрим, что произойдет при смешивании возвращаемых значений и ссылок на значения:
В случае A мы присваиваем ссылку возвращаемого значения переменной, которая сама не является ссылкой. Поскольку value не является ссылкой, то возвращаемое значение просто копируется в value так, как если бы returnByReference() был возвратом по значению.
В случае B мы пытаемся инициализировать ссылку ref копией возвращаемого значения функции returnByValue(). Однако, поскольку возвращаемое значение не имеет адреса (это r-value), мы получим ошибку компиляции.
В случае C мы пытаемся инициализировать константную ссылку cref копией возвращаемого значения функции returnByValue(). Поскольку константные ссылки могут быть инициализированы с помощью r-values, то здесь не должно быть никаких проблем. Обычно r-values уничтожаются в конце выражения, в котором они созданы, однако, при привязке к константной ссылке, время жизни r-value (в данном случае, возвращаемого значения функции) продлевается в соответствии со временем жизни ссылки (в данном случае, cref ).
Заключение
В большинстве случаев идеальным вариантом для использования является возврат по значению. Это также самый гибкий и безопасный способ возврата данных обратно в вызывающий объект. Однако возврат по ссылке или по адресу также может быть полезен при работе с динамически выделенной памятью. При использовании возврата по ссылке или по адресу убедитесь, что вы не возвращаете ссылку или адрес локальной переменной, которая выйдет из области видимости, когда функция завершит свое выполнение!
Напишите прототипы для каждой из следующих функций. Используйте наиболее подходящие параметры и типы возврата (по значению, по адресу или по ссылке). Используйте const, когда это необходимо.
Задание №1
Функция sumTo(), которая принимает целочисленный параметр, а возвращает сумму всех чисел между 1 и числом, которое ввел пользователь.
Что делает return в Python?
Функция print() записывает, то есть «печатает», строку или число на консоли. Оператор return не выводит значение, которое возвращается при вызове функции. Это, однако, приводит к немедленному завершению или завершению функции, даже если это не последний оператор функции.
Во многих других языках функция, которая не возвращает значение, называется процедурой.
В данном коде значение, возвращаемое (то есть 2) при вызове функции foo(), используется в функции bar(). Эти возвращаемые значения печатаются на консоли только тогда, когда используются операторы печати, как показано ниже.
Пример
Вывод
Мы видим, что когда foo() вызывается из bar(), 2 не записывается в консоль. Вместо этого он используется для вычисления значения, возвращаемого из bar().
Пример оператора return Python
Давайте посмотрим на простой пример сложения двух чисел и возврата суммы вызывающему абоненту.
Мы можем оптимизировать функцию, указав выражение в операторе возврата.
Каждая функция что-то возвращает
Давайте посмотрим, что возвращается, когда функция не имеет оператора возврата.
Что произойдет, если в операторе ничего нет?
Когда оператор return не имеет значения, функция возвращает None.
Может иметь несколько операторов
Функция может возвращать несколько типов значений
В отличие от других языков программирования, функции Python не ограничиваются возвратом значений одного типа. Если вы посмотрите на определение функции, в нем нет никакой информации о том, что она может вернуть.
Давайте посмотрим на пример, в котором функция возвращает несколько типов значений.
Возврат нескольких значений в одном операторе
Мы можем вернуть несколько значений из одного оператора возврата. Эти значения разделяются запятой и возвращаются вызывающей программе в виде кортежа.
С блоком finally
Как работает оператор return внутри блока try-except? Сначала выполняется код блока finally перед возвратом значения вызывающей стороне.
Если в блоке finally есть оператор return, то предыдущий оператор return игнорируется и возвращается значение из блока finally.
Урок №12. Функции и оператор возврата return
Обновл. 11 Сен 2021 |
Вы уже знаете, что каждая программа должна содержать функцию main() (с которой она и начинает свое выполнение). Тем не менее, большинство программ используют и много других функций.
Функции
Функция — это последовательность стейтментов для выполнения определенного задания. Часто ваши программы будут прерывать выполнение одних функций ради выполнения других. Вы делаете аналогичные вещи в реальной жизни постоянно. Например, вы читаете книгу и вспомнили, что должны были сделать телефонный звонок. Вы оставляете закладку в своей книге, берете телефон и набираете номер. После того, как вы уже поговорили, вы возвращаетесь к чтению: к той странице, на которой остановились.
Программы на языке C++ работают похожим образом. Иногда, когда программа выполняет код, она может столкнуться с вызовом функции. Вызов функции — это выражение, которое указывает процессору прервать выполнение текущей функции и приступить к выполнению другой функции. Процессор «оставляет закладку» в текущей точке выполнения, а затем выполняет вызываемую функцию. Когда выполнение вызываемой функции завершено, процессор возвращается к закладке и возобновляет выполнение прерванной функции.
Функция, в которой находится вызов, называется caller, а функция, которую вызывают — вызываемая функция, например:
Результат выполнения программы:
Starting main()
In doPrint()
Ending main()
Правило: Не забывайте указывать круглые скобки () при вызове функций.
Возвращаемые значения
Когда функция main() завершает свое выполнение, она возвращает целочисленное значение обратно в операционную систему, используя оператор return.
Функции, которые мы пишем, также могут возвращать значения. Для этого нужно указать тип возвращаемого значения (или «тип возврата»). Он указывается при объявлении функции, перед её именем. Обратите внимание, тип возврата не указывает, какое именно значение будет возвращаться. Он указывает только тип этого значения.
Затем, внутри вызываемой функции, мы используем оператор return, чтобы указать возвращаемое значение — какое именно значение будет возвращаться обратно в caller.
Рассмотрим простую функцию, которая возвращает целочисленное значение:
Результат выполнения программы:
Первый вызов функции return7() возвращает 7 обратно в caller, которое затем передается в std::cout для вывода.
Третий вызов функции return7() опять возвращает 7 обратно в caller. Однако функция main() ничего с ним не делает, поэтому ничего и не происходит (возвращаемое значение игнорируется).
Примечание: Возвращаемые значения не выводятся на экран, если их не передать объекту std::cout. В последнем вызове функции return7() значение не отправляется в std::cout, поэтому ничего и не происходит.
Тип возврата void
Функции могут и не возвращать значения. Чтобы сообщить компилятору, что функция не возвращает значение, нужно использовать тип возврата void. Взглянем еще раз на функцию doPrint() из вышеприведенного примера:
Эта функция имеет тип возврата void, который означает, что функция не возвращает значения. Поскольку значение не возвращается, то и оператор return не требуется.
Вот еще один пример использования функции типа void:
Второй вызов функции returnNothing() даже не скомпилируется. Функция returnNothing() имеет тип возврата void, который означает, что эта функция не возвращает значения. Однако функция main() пытается отправить это значение (которое не возвращается) в std::cout для вывода. std::cout не может обработать этот случай, так как значения на вывод не предоставлено. Следовательно, компилятор выдаст ошибку. Вам нужно будет закомментировать эту строку, чтобы компиляция прошла успешно.
Возврат значений функцией main()
Почему нужно возвращать значения обратно в операционную систему? Дело в том, что возвращаемое значение функции main() является кодом состояния, который сообщает операционной системе об успешном или неудачном выполнении программы. Обычно, возвращаемое значение 0 (ноль) означает что всё прошло успешно, тогда как любое другое значение означает неудачу/ошибку.
Обратите внимание, по стандартам языка C++ функция main() должна возвращать целочисленное значение. Однако, если вы не укажете return в конце функции main(), компилятор возвратит 0 автоматически, если никаких ошибок не будет. Но рекомендуется указывать return в конце функции main() и использовать тип возврата int для функции main().
Еще о возвращаемых значениях
Во-вторых, когда процессор встречает в функции оператор return, он немедленно выполняет возврат значения обратно в caller и точка выполнения также переходит в caller. Любой код, который находится за оператором return в функции — игнорируется.
Функция может возвращать только одно значение через return обратно в caller. Это может быть либо число (например, 7 ), либо значение переменной, либо выражение (у которого есть результат), либо определенное значение из набора возможных значений.
Но есть способы обойти правило возврата одного значения, возвращая сразу несколько значений, но об этом детально мы поговорим на соответствующем уроке.
Наконец, автор функции решает, что означает её возвращаемое значение. Некоторые функции используют возвращаемые значения в качестве кодов состояния для указания результата выполнения функции (успешно ли выполнение или нет). Другие функции возвращают определенное значение из набора возможных значений. Кроме того, существуют функции, которые вообще ничего не возвращают.
Повторное использование функций
Одну и ту же функцию можно вызывать несколько раз, даже в разных программах, что очень полезно: