Оператор return в функциях. Функциональное программирование
На прошлом занятии мы увидели, как их можно объявлять и вызывать. Сегодня сделаем следующий шаг и разберемся, как функции могут возвращать результаты своей деятельности.
Я открою программу, которую мы делали на предыдущем занятии с функцией send_mail(). И давайте здесь объявим еще одну функцию, которая бы вычисляла квадратный корень из положительных чисел:
def get_sqrt(x): res = None if x 0 else x ** 0.5
Обратите внимание, что в соответствии со стандартом PEP8 каждое объявление функции разделяется двумя пустыми строчками. Рекомендуется так делать, чтобы текст программы был хорошо читаем.
Итак, у нас здесь функция с именем get_sqrt(), которое я сам придумал и одним параметром x. Внутри функции я воспользовался тернарным условным оператором, так что переменная res будет принимать None для отрицательных значений и квадратный корень – для неотрицательных.
Давайте попробуем ее вызвать и посмотрим, что она возвратит:
a = get_sqrt(49) print(a)
Во-первых, мы здесь видим новую конструкцию: переменной a присваиваем вызов функции. Это следует воспринимать так, что переменная a будет ссылаться на результат работы этой функции. Что такое результат работы функции, мы сейчас узнаем. В данном случае, значение a равно None. Фактически, это означает, что функция ничего не возвращает, никакого результата! Но почему? Мы же в теле этой функции делаем вычисление квадратного корня? И аргумент передаем положительный. Все дело в том, что внутри функции нужно явно указать, что именно она должна вернуть. Делается это с помощью специального оператора return, после которого через пробел указываются данные, которые будут возвращены. В данном случае, пропишем переменную res.
Снова запустим программу и, смотрите, теперь наша переменная a ссылается на вычисленное значение. Как это произошло? Оператор res вернул объект с вычисленным значением 7.0 и это означает, что функция возвращает этот объект. Затем, с помощью оператора присваивания, создалась переменная a со ссылкой на этот объект. Поэтому при выводе этой переменной, мы видим значение 7.0
Причем, вот этот вот параметр x и переменная res существуют только в момент вызова функции get_sqrt() и пропадают за ее пределами. Мы об этом еще поговорим. Но, пока имейте в виду, что за пределами функции вывести напрямую переменную res, например, не получится:
print(a, res)
возникнет ошибка, что имя res не определено.
Внутри тела функции можно указывать только один оператор return, либо ни одного, тогда функция будет возвращать значение None, как мы только что видели. Но, что если все же прописать в функции два оператора return, что будет? Давайте посмотрим:
def get_sqrt(x): res = None if x 0 else x ** 0.5 return res return x
Нам интегрированная среда здесь сразу указывает писать этот оператор без отступов. Сейчас вы поймете почему. Запускаем программу и видим, что никаких ошибок нет и отображается прежнее значение 7.0. Дело в том, что функция завершает свою работу сразу, как только встретит оператор return. Поэтому, как только была выполнена строчка return res, все остальные команды в теле функции просто игнорируются. Убедимся в этом на отладке (убеждаемся). Поэтому второй return здесь просто бессмысленен – он никогда не будет выполнен. Равно, как и любая другая команда, например, функция print():
def get_sqrt(x): res = None if x 0 else x ** 0.5 return res print(x)
А вот если ее записать до этого оператора, то увидим вывод x, а затем, вычисленного значения res.
Но все же, что делать, если нам нужно вернуть оба значения и res и x? Для этого следует поместить эти переменные в коллекцию, обычно, кортеж и вернуть ее:
def get_sqrt(x): res = None if x 0 else x ** 0.5 return (res, x)
На практике часто не пишут круглые скобки, а просто записывают элементы через запятую:
return res, x
В дальнейшем, я именно так и буду делать. Причем, теперь, мы можем принимать данные, используя множественное присваивание:
a, b = get_sqrt(49) print(a, b)
Видите, как это удобно, легко и наглядно делается в языке Python. Далеко не во всех языках программирования можно вот так запросто вернуть несколько значений через функцию.
Давайте зададим в программе еще одну функцию для определения максимального значения среди двух чисел:
def get_max2(a, b): return a if a > b else b
Казалось бы, что может быть примечательного в такой простой функции. Но, не торопитесь, сейчас кое-какая магия откроется перед вами. Вызвать эту функцию можно, очевидным образом, например, так:
x, y = 5, 7 print(get_max2(x, y))
Я здесь специально определил дополнительно две переменные x, y, чтобы показать, что их также можно спокойно передавать в качестве аргументов. После запуска в консоли увидим максимальное значение 7.
Давайте теперь усложним задачу и будем искать максимум среди трех чисел. Помните, для этого мы использовали вложенные условия. Здесь же, поступим иначе. Определим три переменные и воспользуемся все той же функцией get_max2():
x, y, z = 5, 7, 10 print(get_max2(x, get_max2(y, z)))

Вот это и есть обещанная магия. Смотрите, как это работает. Сначала будет вызвана функция, записанная в качестве аргумента, которая возвратит максимальное среди чисел 7 и 10, то есть, значение 10, а затем, вызывается первая функция, которая определяет максимум из чисел 5 и 10. Соответственно, на выходе получаем результат 10, который и выводится в консоль. Вот так функции можно записывать в аргументах и использовать в своих программах. Мало того, мы можем ту же самую конструкцию использовать и при объявлении новой функции, определяющей максимум среди трех чисел:
def get_max3(a, b, c): return get_max2(a, get_max2(b, c))
А, затем, просто вызвать ее с тремя аргументами:
print(get_max3(x, y, z))
Видите, как элегантно можно решить эту задачу, используя функциональный подход в программировании. Разумеется, здесь функция get_max3() должна объявляться после функции get_max2(), так как использует ее, иначе, мы бы получили ошибку.
Вообще, определение (объявление) функций в Python очень похоже на объявление переменных. Например, в программе, нам никто не запрещает объявить некую переменную с именем get_rect и присвоить ей значение 1 или 2 в зависимости от значения другой переменной PERIMETR:
PERIMETR = True if PERIMETR: get_rect = 1 else: get_rect = 2
Но оказывается, то же самое можно делать и на уровне функций, вместо переменной get_rect будем объявлять разные функции:
if PERIMETR: def get_rect(a, b): return 2 * (a + b) else: def get_rect(a, b): return a * b
И, если сейчас вызвать ее:
print(get_rect(1.5, 3.8))
то получим вычисление периметра прямоугольника. Если же переменную PERIMETR изменить на False:
PERIMETR = False
то функция с именем get_rect() теперь будет вычислять площадь прямоугольника. Здорово, да! Какая гибкость определения функций в языке Python! Такого мало где встретишь.
Наконец, мы можем вообще убрать условие и дважды определить одну и ту же функцию:
def get_rect(a, b): return 2 * (a + b) def get_rect(a, b): return a * b
К ошибкам это не приведет, а просто ссылка get_rect будет инициализирована на второй объект-функцию и, соответственно, она и будет вызвана.
В заключение занятия приведу еще один пример использования функций. Объявим функцию для определения четности числа:
def even(x): return x % 2 == 0
А, затем, вызовем ее в цикле для определения: является ли текущее число четным:
for i in range(1, 20): if even(i): print(i)
После запуска в консоли увидим отображение только четных чисел.
На этом мы завершим наше второе занятие по функциям. Из него вам должно быть понятно, как и для чего используется оператор return, как вызываются функции, записанные в аргументах другой функции, а также объявление функций, подобно переменным. Если все это, действительно, понятно, то переходите к практическим заданиям, пока я собираюсь с мыслями для следующего урока.
Видео по теме

#1. Первое знакомство с Python Установка на компьютер

#2. Варианты исполнения команд. Переходим в PyCharm

#3. Переменные, оператор присваивания, функции type и id

#4. Числовые типы, арифметические операции

#5. Математические функции и работа с модулем math

#6. Функции print() и input(). Преобразование строк в числа int() и float()

#7. Логический тип bool. Операторы сравнения и операторы and, or, not

#8. Введение в строки. Базовые операции над строками

#9. Знакомство с индексами и срезами строк

#10. Основные методы строк

#11. Спецсимволы, экранирование символов, row-строки

#12. Форматирование строк: метод format и F-строки

#13. Списки — операторы и функции работы с ними

#14. Срезы списков и сравнение списков

#15. Основные методы списков

#16. Вложенные списки, многомерные списки

#17. Условный оператор if. Конструкция if-else

#18. Вложенные условия и множественный выбор. Конструкция if-elif-else

#19. Тернарный условный оператор. Вложенное тернарное условие

#20. Оператор цикла while

#21. Операторы циклов break, continue и else

#22. Оператор цикла for. Функция range()

#23. Примеры работы оператора цикла for. Функция enumerate()

#24. Итератор и итерируемые объекты. Функции iter() и next()

#25. Вложенные циклы. Примеры задач с вложенными циклами

#26. Треугольник Паскаля как пример работы вложенных циклов

#27. Генераторы списков (List comprehensions)

#28. Вложенные генераторы списков

#29. Введение в словари (dict). Базовые операции над словарями

#30. Методы словаря, перебор элементов словаря в цикле

#31. Кортежи (tuple) и их методы

#32. Множества (set) и их методы

#33. Операции над множествами, сравнение множеств

#34. Генераторы множеств и генераторы словарей

#35. Функции: первое знакомство, определение def и их вызов

#36. Оператор return в функциях. Функциональное программирование

#37. Алгоритм Евклида для нахождения НОД

#38. Именованные аргументы. Фактические и формальные параметры

#39. Функции с произвольным числом параметров *args и **kwargs

#40. Операторы * и ** для упаковки и распаковки коллекций

#41. Рекурсивные функции

#42. Анонимные (lambda) функции

#43. Области видимости переменных. Ключевые слова global и nonlocal

#44. Замыкания в Python

#45. Введение в декораторы функций

#46. Декораторы с параметрами. Сохранение свойств декорируемых функций

#47. Импорт стандартных модулей. Команды import и from

#48. Импорт собственных модулей

#49. Установка сторонних модулей (pip install). Пакетная установка

#50. Пакеты (package) в Python. Вложенные пакеты

#51. Функция open. Чтение данных из файла

#52. Исключение FileNotFoundError и менеджер контекста (with) для файлов

#53. Запись данных в файл в текстовом и бинарном режимах

#54. Выражения генераторы

#55. Функция-генератор. Оператор yield

#56. Функция map. Примеры ее использования

#57. Функция filter для отбора значений итерируемых объектов

#58. Функция zip. Примеры использования

#59. Сортировка с помощью метода sort и функции sorted

#60. Аргумент key для сортировки коллекций по ключу

#61. Функции isinstance и type для проверки типов данных

#62. Функции all и any. Примеры их использования

#63. Расширенное представление чисел. Системы счисления

#64. Битовые операции И, ИЛИ, НЕ, XOR. Сдвиговые операторы

#65. Модуль random стандартной библиотеки

#66. Аннотация базовыми типами

#67. Аннотации типов коллекций

#68. Аннотации типов на уровне классов

#69. Конструкция match/case. Первое знакомство

#70. Конструкция match/case с кортежами и списками

#71. Конструкция match/case со словарями и множествами

#72. Конструкция match/case. Примеры и особенности использования
© 2023 Частичное или полное копирование информации с данного сайта для распространения на других ресурсах, в том числе и бумажных, строго запрещено. Все тексты и изображения являются собственностью сайта
Что такое return в Python?
Оператор return используется в функциях для возвращения данных после выполнения работы самой функции.
Если функция должна обработать какие-то данные и потом вернуть их, то для возвращения этих данных необходим этот оператор. Рассмотрим все на примере:
def some_test(a, b, c): # Функция с 3 параметрами return a + b + c # Функция возвращает результат суммы чисел res = some_test(4, 6, 1) print(res)
В примере выше вызывается функция, которая считает сумму трех переданных аргументов. В конце функция возвращает это значение, поэтому мы можем записать функцию, как присвоение данных к переменной. В результате этой программы в консоль будет выведено число 11.
Комментарии (10)
Tim 11 октября 2023 в 04:48
Смотри более понятнее,
Есть два вида функций
Первый это как print() она выводит то что в ней написано и не делает что-то более, и не имеет в себе значений,
Второй вид функций это к примеру как input() она выполняет команду спросить и может хранить в себе какое-то значение, к примеру ты же не можешь в переменную запихнуть print потомучто функция print делает только действие, и не может хранит в себе какое-то значение которое может поместить в переменную, а к примеру с input когда эта функция задает тебе вопрос в консоли, то ты написав ей ответ, то в input задаётся значение то которое ты написал в ответе, и это можно использовать в переменных. Если под итожить то когда есть return в функции, то эта функция может хранить в себе какое-то значение, а если нет return, то функция выполняет какое-то действие и не более.
Tim 11 октября 2023 в 05:00
1. **Функции без `return` (подобно `print()`):**
— Они выполняют какое-то действие, но не возвращают значения, которые можно сохранить в переменной.
— Просто выводят информацию на экран или выполняют какие-то действия, но не предоставляют результат, который можно использовать далее в программе.
greet(«Анна») # Эта функция выводит приветствие, но не возвращает значение.
«`
2. **Функции с `return` (подобно `input()`):**
— Они выполняют какое-то действие, но также возвращают значение, которое можно сохранить в переменной и использовать далее.
— Возвращенное значение может быть использовано для присваивания переменным или в выражениях.
Пример:
«`python
def add(a, b):
result = a + b
return result # Эта функция возвращает сумму a и b.
sum_result = add(3, 5) # Результат функции сохраняется в sum_result.
print(sum_result) # Выведет 8
«`
Ваши пояснения о том, как функции работают, в целом верны. Функции с `return` могут хранить возвращенные значения, которые затем можно использовать в вашей программе.
дреш 05 сентября 2023 в 08:57
если человеческим языком, то вызывая функцию, ты запрашиваешь от неё ответ, возвращение значения=ответ на вызов функции
ты прописал функцию (спросил у неё)
она вернула значения (ответила)
Александр 25 июня 2023 в 12:44
5. Функции, возвращающие значения¶
Встроенные функции, которыми мы пользовались, такие как abs , pow и max , возвращают результат. Вызов каждой из этих функций производит значение, которое обычно присваивается переменной или используется в выражении.
biggest = max(3, 7, 2, 5) x = abs(3 - 11) + 10
До сих пор ни одна из написанных нами функций не возвращала значения.
В этой главе мы будем писать функции, возвращающие значения. Первый пример — функция area (англ.: площадь), возвращающая площадь круга с указанным радиусом:
def area(radius): temp = 3.14159 * radius**2 return temp
Мы уже встречали предложение return . Но в функции, возвращающей значение, предложение return включает выражение для возвращаемого значения. Выражение может быть сколь угодно сложным, поэтому функция может быть записана более кратко:
def area(radius): return 3.14159 * radius**2
Однако имейте в виду, что временные переменные, такие как temp , часто делают отладку проще.
Функция может иметь несколько предложений return, по одному в каждой ветке условного выполнения. Мы уже видели встроенную функцию abs , а теперь напишем нашу собственную:
def absolute_value(x): if x 0: return -x else: return x
Поскольку предложения return здесь находятся в альтернативных ветках потока выполнения, будет выполнено только одно из них. Как только это произойдет, функция завершится; никакие последующие предложения выполняться не будут.
В рассматриваемой функции можно опустить else и просто поместить второе предложение return после составного предложения if .
def absolute_value(x): if x 0: return -x return x
Посмотрите внимательно на эту версию и убедитесь, что она работает так же, как и первая.
Код, расположенный после предложения return , или в любом другом месте, которого никогда не сможет достичь поток выполнения, называется мертвым кодом.
Стоит убедиться в том, что в возвращающей значение функции каждый из возможных путей выполнения содержит предложение return . В следующей версии функции absolute_value это не так:
def absolute_value(x): if x 0: return -x elif x > 0: return x
Эта функция некорректна, поскольку, если x окажется равным 0, ни одно из условий не выполнится и функция закончится, не выполнив предложения return . В таком случае, возвращаемым значением будет специальное значение None (англ.: ничто):
>>> print absolute_value(0) None
None является единственным значением типа NoneType :
>>> type(None)
Все функции Python, если не возвращают некоторое значение явно, возвращают None .
5.2. Разработка программы¶
К этому моменту вы уже должны уметь, посмотрев на функцию на языке Python, сказать, что она делает. Выполняя упражнения, вы написали несколько небольших функций. А когда вы начнете писать большие, то наверняка столкнетесь с трудностями, связанными с ошибками выполнения и семантическими ошибками.
Для того, чтобы разрабатывать программы все возрастающей сложности, рассмотрим прием, называемый инкрементной разработкой. Цель инкрементной разработки — избежать длительной и мучительной отладки программы. Это становится возможным, если за один раз добавлять и тестировать небольшой объем кода.
Предположим, вы хотите найти расстояние между двумя точками, заданными с помощью их координат (x1, y1) и (x2, y2). Согласно теореме Пифагора, расстояние составляет:

Первый шаг разработки — обдумать, как должна выглядеть функция distance на языке Python. Другими словами, что должно быть у функции на входе (параметры) и что — на выходе (возвращаемое значение)?
В данном случае, на вход функции подаются две точки, которые можно представить четырьмя параметрами. А возвращаемое значение — расстояние, представленное числом с плавающей точкой.
Теперь можно набросать эскиз функции:
def distance(x1, y1, x2, y2): return 0.0
Очевидно, что эта версия функции не вычисляет расстояние; она всегда возвращает ноль. Однако она синтаксически корректна, и она будет выполняться, а это значит, что ее можно протестировать. И только после этого усложнять.
Чтобы протестировать эту функцию, вызовем её с тестовыми значениями:
>>> distance(1, 2, 4, 6) 0.0
Значения параметров подобраны так, чтобы горизонтальное расстояние равнялось 3, а вертикальное равнялось 4. Таким образом, результат должен быть равен 5 — гипотенуза прямоугольного треугольника со сторонами 3-4-5, изображенного на рисунке. При тестировании функции полезно заранее знать правильный ответ.

Убедившись, что функция синтаксически корректна, начнем добавлять строки кода. После каждого инкрементного изменения, мы будем вновь тестировать функцию. Если в какой-то момент возникнет ошибка, мы будем знать, где её искать — в последней добавленной строке.
Первый шаг состоит в нахождении разностей x2— x1и y2— y1. Мы сохраним эти значения во временных переменных dx и dy и выведем их.
def distance(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 print "dx is", dx print "dy is", dy return 0.0
Функция должна вывести 3 и 4. Если так и произошло, то теперь мы знаем, что первый шаг вычислений выполняется правильно. Если нет, то нужно проверить всего несколько строк.
Далее мы подсчитываем сумму квадратов dx и dy :
def distance(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 dsquared = dx**2 + dy**2 print "dsquared is: ", dsquared return 0.0
Обратите внимание, что мы удалили предложения print , написанные на предыдущем шаге. Подобный код, используемый временно в ходе разработки, называется вспомогательным кодом, или отладочным. Он играет роль строительных лесов при “строительстве” программы, но сам не является частью окончательной версии программы.
И вновь мы запустим программу и проверим её вывод. Должно получиться 25.
Наконец, используя степень 0.5 для нахождения квадратного корня, мы вычислим и вернем результат:
def distance(x1, y1, x2, y2): dx = x2 - x1 dy = y2 - y1 dsquared = dx**2 + dy**2 result = dsquared**0.5 return result
Если эта версия работает правильно, значит, программа готова. В противном случае, чтобы внести ясность, попробуйте вывести значение result перед предложением return.
Пока вы делаете первые шаги в программировании, добавляйте в вашу программу по строчке или две за один раз. Набравшись опыта, вы начнете писать и отлаживать более крупные участки кода. Инкрементная разработка позволит вам сэкономить время на отладке и сделает вашу работу эффективнее.
Придерживайтесь следующих правил:
- Начните с работающей программы и делайте небольшие инкрементные изменения. В каждый момент, когда вы столкнетесь с ошибкой, вы будете знать, где она.
- Используйте временные переменные для сохранения промежуточных результатов, так чтобы их можно было вывести и проверить.
- Если программа работает, то можно удалить вспомогательный код и собрать отдельные предложения в составные выражения. Однако это не должно сделать программу трудной для чтения!
5.3. Композиция¶
Как вы уже знаете, можно вызывать одну функцию из другой. Этот прием называется композиция.
Напишем функцию, которая принимает в качестве входных параметров две точки, центр окружности и точку на периметре, и расчитывает площадь круга.
Пусть координаты центральной точки хранятся в переменных xc и yc , а координаты точки на периметре окружности — в переменных xp и yp . Первым шагом будет нахождение радиуса окружности, равного расстоянию между этими двумя точками. Для этого воспользуемся функцией distance , которая делает именно то, что нам нужно:
radius = distance(xc, yc, xp, yp)
Второй шаг — найти площадь круга данного радиуса и вернуть её. И снова мы воспользуемся одной из ранее написанных функций:
result = area(radius) return result
Оформив этот код в виде функции, получаем:
def area2(xc, yc, xp, yp): radius = distance(xc, yc, xp, yp) result = area(radius) return result
Мы назвали эту функцию area2 , чтобы отличать её от написанной ранее функции area . Внутри некоторого модуля может быть только одна функция с данным именем.
Временные переменные radius и result полезны для разработки и отладки, но, как только получена работающая программа, можно сделать ее более компактной, комбинируя предложения и вызовы функций:
def area2(xc, yc, xp, yp): return area(distance(xc, yc, xp, yp))
5.4. Логические функции¶
Функции могут возвращать логические значения и использоваться в условных предложениях для проверки условий. Часто оказывается удобным спрятать сложные проверки внутри функции. Например:
def is_divisible(x, y): if x % y == 0: return True else: return False
Имя этой функции is_divisible . Принято давать логическим функциям имена, выглядящие как вопрос, предполагающий один из двух возможных ответов: да или нет. Функция is_divisible возвращает либо True либо False , тем самым показывая, делится или не делится x на y .
Можно сделать эту функцию более компактной, воспользовавшись тем, что условие предложения if само по себе является логическим выражением. Мы можем непосредственно вернуть значение этого выражения, вовсе исключив предложение if из программы:
def is_divisible(x, y): return x % y == 0
А вот новая функция в действии:
>>> is_divisible(6, 4) False >>> is_divisible(6, 3) True
Логические функции часто используются в условных предложениях:
if is_divisible(x, y): print "x is divisible by y" else: print "x is not divisible by y"
У вас может появиться соблазн написать:
if is_divisible(x, y) == True:
Но дополнительное сравнение здесь лишнее.
5.5. Тип function ¶
В Python function (англ.: функция) также является типом, как и уже известные нам int , float , str , bool и NoneType .
>>> def func(): . return "function func was called. " . >>> type(func) >>>
Точно так же, как значения других типов, функции могут быть переданы другим функциям в качестве аргументов:
def f(n): return 3*n - 6 def g(n): return 5*n + 2 def h(n): return -2*n + 17 def doto(value, func): return func(value) print doto(7, f) print doto(7, g) print doto(7, h)
Функция doto вызывается три раза. В каждом вызове аргументом для value является 7, а для func — функции f , g и h , по очереди. Этот скрипт выводит:
15 37 3
Этот пример, конечно, надуманный. Но позднее мы встретимся с ситуациями, когда передача функции в качестве аргумента другой функции очень полезна.
5.6. Оформление программ¶
Читабельность программ очень важна для программистов, поскольку на практике читать и изменять программы приходится гораздо чаще, чем писать новые. Все примеры кода в этой книге соответствуют Python Enhancement Proposal 8 (PEP 8). Это руководство по стилю программирования, разработанное сообществом программистов Python.
Чем сложнее становятся программы, тем большую роль начинает играть стиль программирования. Нескольких важных правил полезно придерживаться с самого начала:
- используйте 4 пробела для отступа,
- помещайте предложения import в начало файла,
- отделяйте определения функций двумя пустыми строчками,
- размещайте определения функций все вместе,
- размещайте предложения верхнего уровня, включая вызовы функций, все вместе в конце скрипта.
5.7. Строки в тройных кавычках¶
В дополнение к строкам, заключенным в одинарные и двойные кавычки, с которыми мы впервые встретились в разделе Значения и типы главы 2, в Python также имеются строки в тройных кавычках:
>>> type("""This is a triple quoted string using 3 double quotes.""") >>> type('''This triple quoted strings uses 3 single quotes.''') >>>
Строки в тройных кавычках могут содержать внутри как одинарные, так и двойные кавычки:
>>> print '''"Oh no", she exclaimed, "Ben's bike is broken!"''' "Oh no", she exclaimed, "Ben's bike is broken!" >>>
Кроме того, строковые значения, заключенные в тройные кавычки, могут распространяться на несколько строк:
>>> message = """This message will . span several . lines.""" >>> print message This message will span several lines. >>>
5.8. Модульное тестирование с помощью doctest ¶
В последнее время широкую известность получило автоматическое модульное тестирование (англ.: unit testing) — очень полезная практика разработки программ. Модульное тестирование позволяет убедиться, что отдельные части кода, такие как функции, работают правильно.
Русскоязычный термин модульное тестирование не связан с понятием модуль языка Python, а подразумевает тестирование отдельных частей кода, написанных на любом языке программирования, то есть, модулей как элементов программы в самом общем смысле.
Автоматическое тестирование означает, что однажды написанные модульные тесты могут многократно автоматически выполняться, причем результат их выполнения автоматически оценивается как успешный либо неуспешный. Благодаря этому становится возможным, внеся изменения в функцию, быстро проверить, по-прежнему ли функция работает корректно.
В Python имеется встроенный модуль doctest , который облегчает создание и выполнение модульных тестов. Модульные тесты, заключенные в тройные кавычки, можно писать, начиная с первой строки тела функции или скрипта. Они включают предложения Python для выполнения и вывод, ожидаемый как результат выполнения предложения.
Модуль doctest автоматически выполняет предложения, начинающиеся с >>> , и сравнивает следующую строку с тем, что вывел интерпретатор.
Чтобы посмотреть, как это работает, поместите следующее в скрипт с именем myfunctions.py :
def is_divisible_by_2_or_5(n): """ >>> is_divisible_by_2_or_5(8) True """ if __name__ == '__main__': import doctest doctest.testmod()
Последние три строки заставляют doctest выполняться. Помещайте их в конец файла, если файл содержит доктесты. Вы узнаете, как это работает, когда мы будем обсуждать модули.
Запустив скрипт на выполнение, получим следующее:
$ python myfunctions.py ********************************************************************** File "myfunctions.py", line 3, in __main__.is_divisible_by_2_or_5 Failed example: is_divisible_by_2_or_5(8) Expected: True Got nothing ********************************************************************** 1 items had failures: 1 of 1 in __main__.is_divisible_by_2_or_5 ***Test Failed*** 1 failures. $
Это пример неуспешного теста. Тест ожидает, что вызов is_divisible_by_2_or_5(8) даст результат True . Поскольку вызов is_divisible_by_2_or_5 не вернул ничего, тест считается неуспешным, и doctest сообщает, что ожидалось значение True , но не было получено ничего.
Заставим этот тест выполняться, возвращая True :
def is_divisible_by_2_or_5(n): """ >>> is_divisible_by_2_or_5(8) True """ return True if __name__ == '__main__': import doctest doctest.testmod()
Если теперь запустить скрипт, он не выведет ничего. Это значит, что тест прошел успешно. Еще раз обратите внимание, что строка с тестом должна быть помещена сразу после заголовка в определении функции.
Чтобы увидеть более подробный отчет о выполнении теста, запустите скрипт с опцией -v :
$ python myfunctions.py -v Trying: is_divisible_by_2_or_5(8) Expecting: True ok 1 items had no tests: __main__ 1 items passed all tests: 1 tests in __main__.is_divisible_by_2_or_5 1 tests in 2 items. 1 passed and 0 failed. Test passed. $
Хотя тест проходит, наш набор тестов явно неадекватен, так как функция is_divisible_by_2_or_5 возвращает True независимо от переданных ей аргументов. Но вот окончательная версия набора тестов и корректного кода:
def is_divisible_by_2_or_5(n): """ >>> is_divisible_by_2_or_5(8) True >>> is_divisible_by_2_or_5(7) False >>> is_divisible_by_2_or_5(5) True >>> is_divisible_by_2_or_5(9) False """ return n % 2 == 0 or n % 5 == 0 if __name__ == '__main__': import doctest doctest.testmod()
Теперь запустите скрипт с опцией -v и посмотрите, что получится.
5.9. Глоссарий¶
None Специальное значение Python, возвращаемое функцией, в которой либо нет предложения return, либо предложение return без аргумента. None — единственное значение типа NoneType . возвращаемое значение Значение, возвращаемое функцией. Вызывающий код получает это значение как результат вызова функции. временная переменная Переменная, используемая для хранения промежуточного результата вычислений. вспомогательный код Код, полезный для отладки программы в ходе ее разработки, но не включаемый в окончательную версию программы. инкрементная разработка Процесс разработки программы, нацеленный на то, чтобы избежать длительной отладки, за счет добавления и тестирования только небольших кусков кода за один раз. композиция функций Вызов одной функции в теле другой, или использование возвращаемого функцией значения в качестве аргумента при вызове другой функции. логическая функция Функция, возвращающая логическое значение. мертвый код Часть программы, которая не может быть выполнена ни при каких обстоятельствах, часто из-за того, что располагается после предложения return . модульное тестирование Практика программирования, нацеленная на проверку того, что отдельные части программы работают корректно. В Python имеется встроенный модуль doctest для автоматического выполнения модульных тестов.
5.10. Упражнения¶
Все упражнения, приведенные ниже, добавляйте в файл ch05.py , в конце которого поместите следующие строки:
if __name__ == '__main__': import doctest doctest.testmod()
Выполнив каждое из упражнений, запускайте скрипт, чтобы убедиться, что доктест для только что написанной функции проходит.
-
Напишите функцию compare , которая возвращает 1 , если a > b , 0 , если a == b и -1 , если a < b . Поместите тело функции после следующих доктестов и убедитесь, что они успешно проходят.
def compare(a, b): """ >>> compare(5, 4) 1 >>> compare(7, 7) 0 >>> compare(2, 3) -1 >>> compare(42, 1) 1 """
def hypotenuse(a, b): """ >>> hypotenuse(3, 4) 5.0 >>> hypotenuse(12, 5) 13.0 >>> hypotenuse(7, 24) 25.0 >>> hypotenuse(9, 12) 15.0 """
def slope(x1, y1, x2, y2): """ >>> slope(5, 3, 4, 2) 1.0 >>> slope(1, 2, 3, 2) 0.0 >>> slope(1, 2, 3, 3) 0.5 >>> slope(2, 4, 1, 2) 2.0 """
def intercept(x1, y1, x2, y2): """ >>> intercept(1, 6, 3, 12) 3.0 >>> intercept(6, 1, 1, 6) 7.0 >>> intercept(4, 6, 12, 8) 5.0 """
def is_factor(f, n): """ >>> is_factor(3, 12) True >>> is_factor(5, 12) False >>> is_factor(7, 14) True >>> is_factor(2, 14) True >>> is_factor(7, 15) False """
def is_multiple(m, n): """ >>> is_multiple(12, 3) True >>> is_multiple(12, 4) True >>> is_multiple(12, 5) False >>> is_multiple(12, 6) True >>> is_multiple(12, 7) False """
def f2c(t): """ >>> f2c(212) 100 >>> f2c(32) 0 >>> f2c(-40) -40 >>> f2c(36) 2 >>> f2c(37) 3 >>> f2c(38) 3 >>> f2c(39) 4 """
def c2f(t): """ >>> c2f(0) 32 >>> c2f(100) 212 >>> c2f(-40) -40 >>> c2f(12) 54 >>> c2f(18) 64 >>> c2f(-48) -54 """
Просмотр
© Copyright 2009, 2012, Джеффри Элкнер, Аллен Б. Дауни, Крис Мейерс, Андрей Трофимов. При создании использован Sphinx 1.1.3.
Оператор return в Python: возврат значений из функции
Оператор return в Python используется для возврата значения из функции. Пользователь может использовать оператор возврата только в функции. Его нельзя использовать вне функции Python. Оператор возврата включает ключевое слово return и значение, которое будет возвращено после этого.
Синтаксис оператора возврата:
def funtion_name(): statements . . . return [expression]
def adding(x, y): i = x + y return i result = adding(16, 25) print(f'Output of adding(16, 25) function is ')

def adding(a, b): # this function is return the value of(a + b) return a + b def boolean_function(a): # this function is return the Boolean value return bool(a) # calling function flag = adding(2, 3) print("Output of first function is <>".format(flag)) flag = boolean_function(9 < 5) print("\nOutput of second function is <>".format(flag))

Возврат нескольких значений
В языке программирования Python пользователь может возвращать несколько значений из функции. Ниже приведены различные методы для этого.
1. Использование объекта: этот метод похож на C / C ++ и Java. Пользователь может создать класс для хранения нескольких значений в функции и возврата объекта этого класса.
class a: def __init__(self): self.omg = "javatpoint is the best website to learn" self.i = 122 # This function will return an object of the class a def test(): return a() # Driver code to test the above method z = test() print(z.omg) print(z.i)

2. Использование кортежа: кортеж похож на список, но есть небольшая разница между кортежем и списком. В кортеже значения объекта нельзя изменить, а в списке – можно.
def test(): omg = "javatpoint is the best website to learn" i = 122 return omg, i; # Return tuple, we could also. # Driver code to test the above method. omg, i = test() # Assign return tuple print(omg) print(i)

3. Использование списка: список аналогичен массиву динамического размера. В списке пользователь может хранить все в одной переменной.
def test(): omg = "javatpoint" i = 122 return [omg, i]; # Driver code to test the above method list = test() print(list)

4. Использование словаря. В языке Python словарь – это набор неструктурированных элементов, которые используются для хранения значений данных, таких как хэш или карта.
def test(): a = dict(); a['omg'] = "javatpoint" a['i'] = 122 return a # Driver code to test the above method a = test() print(a)

5. Использование класса данных(Python 3.7+)
from dataclasses import dataclass @dataclass class Book_list: bookname: str cost: float quantity_of_book_available: int = 0 # This function is used to calculate the total cost of the books def total_cost_of_book(self) -> float: return self.cost * self.quantity_of_book_available book = Book_list("Python programming language.", 499, 10) i = book.total_cost_of_book() # print the total cost print(i) # print the details of the book print(book)

Функция, возвращающая другую функцию
В языке программирования Python функция имеет форму объекта. Следовательно, пользователь может вернуть функцию из другой функции.
В приведенной ниже программе функция first_add возвращает функцию second_add.
def first_add(x): def second_add(y): return x + y return second_add i = first_add(20) print("The value of x + y is", i(10)) # second function def outer_func(x): return x * 5 def func(): # return the value in the different function return outer_func # storing the function in z z = func() print("\nThe value of x * y is", z(10))