Функции в Python: введение и объект None

Обновлено:

1. Новая большая тема — функции

Следующая большая тема посвящена созданию собственных функций.

Для определения функции в Python используется ключевое слово:

def

Ключевое слово def, параметры, тело функции и вызов собственных функций будут рассматриваться в следующей части.

На этом уроке мы сначала подготовимся к теме и разберём:

  • объект None;
  • возвращаемое значение функции;
  • функции, которые возвращают None;
  • основное назначение функций;
  • устранение дублирования кода.

2. Объект None

В Python существует специальный объект:

None

None обозначает отсутствие значения.

Можно сказать:

В этом месте сейчас нет полезного значения.

None — это не строка, поэтому кавычки не используются.

Правильно:

None

Неправильно:

'None'

Вторая запись является обычной строкой из четырёх символов.


3. None — это полноценный объект

None является полноценным объектом Python.

Его можно сохранить в переменную:

result = None

Теперь имя result ссылается на объект None:

result ─────> None

Правильнее говорить не «пустая переменная», а:

Переменная result ссылается на None.

Или:

В переменной result пока отсутствует полезное значение.


4. В Python существует только один объект None

None является единственным объектом своего типа.

Разные переменные, которым присвоен None, ссылаются на один объект:

first_result = None
second_result = None

Упрощённая схема:

first_result ──┐
               ├────> None
second_result ─┘

В официальной документации None описывается как единственный объект, обозначающий отсутствие значения.


5. None является неизменяемым объектом

Состояние объекта None изменить нельзя.

Нельзя добавить в него число, изменить его содержимое или превратить сам объект None в строку.

Если мы перезапишем переменную:

result = None
result = 25

объект None не изменится.

Имя result просто начнёт ссылаться на другой объект:

Сначала:

result ─────> None

После перезаписи:

result ─────> 25

6. None является встроенной константой

Имя None заранее существует во встроенной области видимости Python.

Его не нужно создавать или импортировать.

Мы можем сразу использовать его:

result = None

Имя None нельзя использовать для своей переменной и нельзя перезаписать. Попытка присваивания приведёт к синтаксической ошибке.

Неправильно:

None = 10

Будет ошибка:

SyntaxError

7. Размер объекта None

Иногда можно встретить утверждение:

Объект None всегда занимает 16 байт.

Так говорить неправильно.

Размер объекта зависит от:

  • реализации Python;
  • версии Python;
  • разрядности системы;
  • особенностей сборки интерпретатора.

В некоторых версиях 64-битного CPython результат действительно может быть равен 16 байтам, но это не универсальная гарантия языка.

На данном этапе точный размер объекта None запоминать не нужно.

Главное понимать:

  • None — небольшой служебный объект;
  • он существует в единственном экземпляре;
  • разные переменные могут ссылаться на один объект None.

8. Обращение к None в IDLE

В IDLE выполним:

None

Визуально ничего не появится.

Создадим переменную:

result = None

Затем обратимся к ней:

result

IDLE снова ничего не выведет.

Это не означает, что переменная не существует или что в ней ничего нет.

В ней находится объект None.


9. Почему IDLE не показывает None

Интерактивная оболочка IDLE обычно отображает результат введённого выражения.

Например:

10

IDLE покажет:

10

Если ввести:

'Hello'

IDLE покажет:

'Hello'

Но отображение результата None специально подавляется.

Интерактивный механизм Python проверяет результат выражения и ничего не печатает, если результатом является None.

Поэтому None не невидим вообще. Он просто автоматически не отображается как результат выражения в интерактивной оболочке.


10. Как увидеть None

Чтобы явно вывести объект None, используем функцию print():

print(None)

Результат:

None

Пример с переменной:

result = None

print(result)

Результат:

None

Функция print() явно преобразует переданный объект в текстовое представление и выводит его.


11. Для чего используется None

None часто используется как первоначальное значение, когда полезный результат пока неизвестен.

Например:

user_name = None

Это может означать:

Имя пользователя пока не получено.

Другой пример:

discount = None

Это может означать:

Пока неизвестно, будет ли назначена скидка.

Ещё пример:

order_result = None

Это может означать:

Заказ ещё не обработан, поэтому результата пока нет.


12. None как временное значение

Предположим, программа позже должна получить цену товара.

В начале работы цена ещё неизвестна:

product_price = None

Позже нужное значение поступило:

product_price = 1500

Имя product_price начало ссылаться на число:

Сначала:

product_price ─────> None

Позже:

product_price ─────> 1500

Если значение так и не поступило, в переменной останется None.

В будущем мы научимся проверять это с помощью условных конструкций.


13. None не является нулём

None не означает число 0.

number = 0

В переменной находится настоящее целое число.

number = None

В переменной отсутствует числовое значение.

Это разные ситуации.

Например:

  • нулевой баланс — это 0;
  • баланс пока неизвестен — это None.

14. None не является пустой строкой

Пустая строка:

''

является экземпляром класса str.

Она существует и содержит ноль символов.

None:

None

обозначает отсутствие строкового значения.

Например:

  • пользователь оставил пустой текст — '';
  • текст от пользователя ещё не получен — None.

15. None не является пустым списком

Пустой список:

[]

является настоящим списком без элементов.

None означает, что списка пока нет.

Например:

orders = []

может означать:

Список заказов получен, но заказов нет.

А:

orders = None

может означать:

Список заказов ещё не был получен.


16. Функции возвращают значения

Мы уже использовали функции, которые возвращают полезный результат.

Например:

result = len('Hello')

Функция len() возвращает:

5

Поэтому в переменную result записывается число:

result = 5

17. Результат функции sum()

numbers = [10, 20, 30]

result = sum(numbers)

Функция sum() возвращает сумму:

60

Теперь:

print(result)

выведет:

60

Упрощённо выполнение можно представить так:

sum(numbers) ─────> 60

18. Другие возвращаемые значения

Функция abs() возвращает модуль числа:

result = abs(-10)

В переменной находится:

10

Функция max() возвращает максимальный элемент:

result = max([10, 25, 5])

В переменной находится:

25

Функция round() возвращает округлённое значение:

result = round(3.8)

В переменной находится:

4

19. Не каждая функция возвращает полезный результат

Некоторые функции выполняют действие, но не создают полезного результата для дальнейших вычислений.

Например, основная задача функции print():

Вывести информацию на экран.

Функция выполняет эту задачу, но результат печати не нужно возвращать в программу.

Поэтому print() возвращает:

None

20. Что возвращает print()

Рассмотрим код:

result = print('Hello')

Сначала функция выполняет своё основное действие:

Hello

После этого функция возвращает:

None

Именно None записывается в переменную result.

Проверим:

print(result)

Результат:

None

21. Полный пример с print()

result = print('Hello')

print(result)

Результат:

Hello
None

Первая строка появилась потому, что сработала функция:

print('Hello')

Вторая строка появилась потому, что мы отдельно распечатали значение переменной:

print(result)

В переменной result находился объект None.


22. Вывод на экран и возвращаемое значение — не одно и то же

Очень важно различать два действия.

Вывод на экран

print('Hello')

Функция показала текст пользователю.

Возвращаемое значение

result = print('Hello')

После выполнения функции в переменную result записался объект:

None

Текст:

Hello

не записался в переменную result.

Он был только выведен на экран.


23. Пример с задержкой

Для наглядности можно использовать функцию sleep() из модуля time.

from time import sleep

result = print('Hello')

sleep(2)

print(result)

Результат работы:

Hello

После этого программа подождёт примерно две секунды и выведет:

None

Функция sleep() приостанавливает выполнение программы на указанное количество секунд.


24. Порядок выполнения примера

from time import sleep

result = print('Hello')

sleep(2)

print(result)

Python выполняет код сверху вниз.

Сначала:

print('Hello')

выводит:

Hello

Затем возвращает None, который сохраняется в result.

После этого:

sleep(2)

приостанавливает выполнение.

В конце:

print(result)

выводит:

None

25. Функция sleep() тоже возвращает None

Результат sleep() также можно сохранить:

from time import sleep

sleep_result = sleep(2)

print(sleep_result)

Программа подождёт примерно две секунды, после чего выведет:

None

Основная задача sleep() — приостановить выполнение программы.

Она не должна вычислять и возвращать полезное число или строку.


26. Функция должна что-то вернуть

В Python результатом вызова функции всегда становится определённый объект.

Если функция не возвращает полезный результат, результатом является:

None

Собственные функции без явно возвращённого значения тоже будут возвращать None. Подробно это будет рассмотрено после изучения ключевого слова def и возврата результатов.


27. Функции с полезным результатом

Примеры функций, которые возвращают объект для дальнейшей работы:

len('Hello')

возвращает:

5
sum([10, 20, 30])

возвращает:

60
max([10, 20, 30])

возвращает:

30
abs(-10)

возвращает:

10

28. Функции с основным действием

Примеры функций, основная задача которых состоит не в вычислении полезного результата:

print('Hello')

Основное действие — вывод текста.

sleep(2)

Основное действие — пауза в выполнении программы.

После выполнения такие функции возвращают:

None

29. Подсказки Visual Studio Code

Если навести указатель на имя функции в Visual Studio Code, редактор может показать краткую информацию о ней.

Для функции, возвращающей None, в подсказке часто можно увидеть запись:

-> None

Например, такая подсказка означает:

После выполнения функция возвращает объект None.

Точный вид подсказки зависит от установленного расширения, версии Python и настроек редактора.


30. Зачем нужны функции

Функция позволяет один раз описать определённое действие или алгоритм, а затем использовать его много раз.

Например, функция:

sum()

уже содержит алгоритм сложения элементов итерируемого объекта.

Мы можем передать ей разные списки:

first_numbers = [10, 20, 30]
second_numbers = [5, 15, 25]
third_numbers = [100, 200, 300]

И использовать один и тот же готовый алгоритм:

print(sum(first_numbers))
print(sum(second_numbers))
print(sum(third_numbers))

31. Результат примера с sum()

first_numbers = [10, 20, 30]
second_numbers = [5, 15, 25]
third_numbers = [100, 200, 300]

print(sum(first_numbers))
print(sum(second_numbers))
print(sum(third_numbers))

Результат:

60
45
600

Мы использовали один алгоритм три раза.

Нам не пришлось самостоятельно заново описывать сложение элементов каждого списка.


32. Дублирование кода

Дублирование кода — это повторение одинаковых или почти одинаковых участков программы.

Предположим, в программе нужно много раз рассчитывать сумму чисел.

Без готовой функции пришлось бы каждый раз повторять алгоритм:

получить первый элемент;
получить второй элемент;
сложить значения;
получить следующий элемент;
снова сложить;
продолжать до конца объекта.

Если подобных мест много, программа становится:

  • длиннее;
  • сложнее;
  • менее понятной;
  • труднее для исправления;
  • труднее для проверки.

33. Функция избавляет от дублирования

Вместо повторения алгоритма мы вызываем:

sum(numbers)

Название функции сразу показывает, что программа делает:

Вычисляет сумму элементов.

Функция позволяет скрыть сложный алгоритм за коротким и понятным именем.


34. Пример с интернет-магазином

Предположим, интернет-магазин хранит суммы заказов за разные дни:

monday_orders = [1200, 800, 1500]
tuesday_orders = [900, 2100, 500]
wednesday_orders = [1700, 600, 1100]

Общую сумму за каждый день можно получить так:

monday_total = sum(monday_orders)
tuesday_total = sum(tuesday_orders)
wednesday_total = sum(wednesday_orders)

Мы используем одну функцию для разных данных.


35. Пример со складом

Предположим, на разных складах хранится разное количество товаров:

first_warehouse = [10, 20, 30]
second_warehouse = [5, 15, 25]
third_warehouse = [100, 50, 75]

Количество товаров:

first_total = sum(first_warehouse)
second_total = sum(second_warehouse)
third_total = sum(third_warehouse)

Не нужно создавать отдельный алгоритм для каждого склада.


36. Функции делают код короче

Сравним длинное описание:

Возьми каждый элемент списка.
Последовательно сложи все элементы.
Сохрани итоговый результат.

И короткий вызов:

sum(numbers)

Функция делает код компактнее, но при этом не скрывает его смысл.

По названию sum понятно, что вычисляется сумма.


37. Функции делают код понятнее

Хорошее имя функции сообщает, какую задачу она выполняет.

Например:

len(text)

означает получение длины.

max(numbers)

означает поиск максимального значения.

round(price, 2)

означает округление числа.

В будущем мы будем придумывать понятные имена собственным функциям.


38. Функции упрощают исправление кода

Предположим, один алгоритм был скопирован в десять мест программы.

Если в нём обнаружится ошибка, придётся:

  1. найти все десять копий;
  2. исправить каждую;
  3. убедиться, что одна копия не была пропущена.

Если алгоритм находится внутри одной функции, исправляется только сама функция.

Все места, где она вызывается, начнут использовать исправленный вариант.


39. Функции упрощают проверку программы

Небольшую функцию легче проверить отдельно от всей программы.

Например, можно передать ей несколько разных наборов данных и убедиться, что она возвращает правильные результаты.

В дальнейшем мы познакомимся с тестированием функций.


40. Функции разделяют большую программу на части

Большая программа может состоять из множества небольших задач.

Например, программа интернет-магазина должна:

  • рассчитать стоимость заказа;
  • определить скидку;
  • сформировать сообщение;
  • сохранить заказ;
  • отправить уведомление.

Вместо одного огромного участка кода для каждой задачи можно создать отдельную функцию.

Так программу проще читать и развивать.


41. Функции можно переиспользовать

Одну функцию можно вызвать:

  • несколько раз в одном файле;
  • из разных частей программы;
  • в других файлах;
  • в других проектах.

Ранее мы уже видели пример импорта:

from math import prod

Функция prod() была написана разработчиками Python, а мы получили возможность использовать готовый код в своей программе.


42. Функции позволяют использовать чужие алгоритмы

Когда мы вызываем:

sum(numbers)

нам не нужно знать все внутренние детали работы sum().

Нам достаточно знать:

  • что передать;
  • что функция сделает;
  • какой результат она вернёт.

Такая возможность позволяет создавать программы из уже готовых строительных блоков.


43. Функция получает данные и возвращает результат

Упрощённую работу функции можно представить так:

Данные → функция → результат

Например:

[10, 20, 30] → sum() → 60
'Hello' → len() → 5
-10 → abs() → 10

Но иногда результатом является None:

'Hello' → print() → None

При этом функция print() дополнительно выводит текст на экран.


44. Возвращаемое значение можно сохранить

numbers = [10, 20, 30]

total = sum(numbers)

Функция вернула число:

60

Имя total стало ссылаться на этот результат.

После этого результат можно использовать дальше:

rounded_total = round(total)

45. None тоже можно сохранить

result = print('Hello')

Функция вернула:

None

Поэтому переменная result существует и ссылается на полноценный объект.

Просто этот объект сообщает:

Полезного результата нет.


46. Почему функция print() возвращает None

Основная задача print() уже выполнена:

Информация выведена на экран.

Возвращать напечатанный объект обычно не нужно.

Если написать:

result = print('Hello')

функция не возвращает строку 'Hello'.

Она возвращает отсутствие полезного результата:

None

47. Главные преимущества функций

Функции позволяют:

  • не повторять одинаковый код;
  • давать алгоритмам понятные имена;
  • уменьшать размер программы;
  • делить большую программу на части;
  • повторно использовать готовый код;
  • исправлять алгоритм в одном месте;
  • отдельно проверять разные части программы;
  • скрывать сложную внутреннюю реализацию.

48. Что пока не изучаем

На этом уроке мы не рассматриваем:

  • синтаксис определения собственной функции;
  • параметры;
  • аргументы собственных функций;
  • именованные аргументы;
  • значения по умолчанию;
  • ключевое слово return;
  • локальные переменные функции;
  • рекурсию;
  • декораторы.

Эти темы будут изучаться постепенно.

Сейчас важно подготовить основу:

  • понимать объект None;
  • отличать вывод от возвращаемого значения;
  • понимать, что функция может вернуть None;
  • понимать, зачем программа делится на функции.

49. Основные правила урока

None обозначает отсутствие значения:

result = None

None является единственным неизменяемым объектом своего типа.

В IDLE результат None автоматически не отображается:

result

Чтобы увидеть его явно:

print(result)

Функции могут возвращать полезные значения:

result = sum([10, 20, 30])

Результат:

60

Функция print() выполняет вывод, но возвращает:

None

Пример:

result = print('Hello')

print(result)

Результат:

Hello
None

Главное назначение функций:

Один раз описать алгоритм и использовать его многократно, не дублируя код.

В следующей части мы начнём создавать собственные функции с помощью ключевого слова:

def