
О функциях
Использование готовых функций. Приём и возврат значений функций. Свойства функций
Штана Альберт Игоревич
Функции
Вызов функции
Сложение, конкатенация, нахождение остатка от деления и остальные рассмотренные операции — это базовые возможности языков программирования. Математика не ограничена арифметикой, кроме нее есть и другие разделы со своими операциями — например, статистика. То же самое касается и строк: их можно переворачивать, менять регистр букв, удалять лишние символы — и это только самое простое. Еще на более высоком уровне есть прикладная логика конкретного приложения. Программы списывают деньги, считают налоги, формируют отчеты. Количество подобных операций бесконечно и индивидуально для каждой программы. И их нужно уметь выражать в коде. Чтобы выразить любую произвольную операцию, в программировании существует понятие функция. Функции бывают встроенные и добавленные программистом. С одной встроенной функцией мы уже знакомы — это print(). Функции — одна из ключевых конструкций в программировании. Без них невозможно сделать практически ничего. Знакомство с ними нужно начинать как можно раньше, так как весь дальнейший материал оперирует функциями по максимуму. Сначала необходимо научится пользоваться уже созданными функциями, а потом создавать собственные.
Функция len() считает количество символов в строке. Пример ее вызова:
# Вызов функции len с параметром 'Python'
result = len('Python')
print(result) # => 6
Параметры или аргументы — это информация, которую функция получает при вызове. На основе этой информации функция обычно вычисляет и выдает результат. В примере выше мы создали переменную result и указали интерпретатору конкретное действие: надо записать в нее результат, который возвращается функцией len() при ее вызове. В этом смысле функции подобны операциям — они всегда возвращают результат своей работы. Запись len('Python') означает, что вызывается функция с именем len, в которую передали параметр 'Python'. Функция len() считает длину той строки, которую ей передали. Вызов функции всегда обозначается скобками (), которые идут сразу за именем функции. В скобках может быть любое количество параметров, а иногда ни одного. Количество зависит от используемой функции. Возьмем для примера функцию pow(), которая возводит указанное число в нужную степень. Она принимает на вход два параметра: берет первый параметр и возводит его в степень, переданную вторым параметром:
result = pow(2, 4) # 2 * 2 * 2 * 2
print(result) # => 16
Сигнатура функции
Посмотрим на функции, которые возводят число в степень и округляют. Также на их примере разберем, что такое сигнатура, и какие параметры называют обязательными и необязательными.
Функция pow()
Функция pow() возводит число в степень. Она принимает два параметра: какое число возводить и в какую степень возводить. Если вызывать pow() без параметров, то Python выдаст следующее: "TypeError: pow expected at least 2 arguments, got 0". Интерпретатор сообщает, что функция ожидает два параметра, а вы вызвали ее без них. Функция pow() всегда имеет два обязательных параметра, поэтому ее невозможно вызвать с другим количеством параметров. Более того, параметрами pow() могут быть только числа. Например, если передать в нее пару строк, это приведет к следующей ошибке: "TypeError: unsupported operand type(s) for ** or pow(): 'str' and 'str'". Результат вызова функции — тоже всегда число. Другая функция может иметь другое число параметров и другие типы параметров. Например, может существовать функция, которая принимает три параметра: число, строку и еще одно число. Чтобы знать такие подробности о конкретной функции, нужно изучать ее сигнатуру. Она определяет входные параметры и их типы, а также выходной параметр и его тип. Про функцию pow() можно почитать в официальной документации Python. Обычно документация для функции выглядит так:
pow(x, y[, z])
Возвращает x в степени y; если z присутствует, возвращает x в степени y, по модулю z
Первая строка здесь — это сигнатура функции. У функции два обязательных параметра — x и y. Необязательный параметр z указан в квадратных скобках. Следом поясняется, для чего функция нужна. Документация дает понять, сколько аргументов у функции и какого они типа. Также она описывает, что возвращает функция и какого типа будет возвращаемое значение. Рассмотрим еще одну функцию — она округляет число.
Функция round()
Рассмотрим функцию round(), которая округляет переданное ей число:
result = round(9.35, 0) # 9.0
Мы передали в нее два параметра:
- Число, которое нужно округлить
- Точность округления
Создатели функции round сделали второй параметр необязательным и задали ему внутри функции значение по умолчанию None. Если не указывать второй параметр, то результат будет целым значением (int):
result = round(9.23) # 9
А если нужна точность, то можно передать параметр:
# округление до одного знака после запятой
print(round(8.25, 1)) # 8.2
print(round(8.15, 1)) # 8.2
В первом случае округление в меньшую сторону, а во втором случае округление в большую сторону. Согласно документации среднее значение округляется в сторону четного числа. Если функция в Python принимает необязательные аргументы, то они всегда стоят после обязательных. Их количество может быть любым. Это зависит от самой функции, но они всегда идут рядом и в конце списка аргументов.
Вызов функции — выражение
Можно ли вызов функции принять за выражение?
Что принимается за выражение
Выражение в программировании возвращает результат, который можно использовать. Например, такие математические операции, как сложение и вычитание, строковые операции, как конкатенация, — все это выражения. Особенность выражений в том, что они возвращают результат, который можно использовать дальше: например, присвоить переменной или вывести на экран. Так это выглядит в коде:
# Тут выражение — это 1 + 5
summ = 5 + 5
print(summ)
Но не все в программировании — выражение. Определение переменной — это инструкция, значит, она не может быть частью выражения. То есть такой код выдаст ошибку:
# Бессмысленный код, который не сработает
5 + summ = 5 + 5
Теперь разберемся, принимается ли за выражение вызов функции.
Можно ли считать вызов функции выражением
Функции возвращают результат — значит, они выражения. Например, можно использовать вызов функции прямо в математических операциях. Вот как можно получить индекс последнего символа в слове:
name = 'Python'
# Индексы начинаются с нуля
# Вызов функции и вычитание вместе!
last_i = len(name) - 1
print(last_i) # => 5
В этом коде нет нового синтаксиса. Мы всего лишь соединили уже известные части, опираясь на их природу. Можно пойти еще дальше:
name = 'Python'
print(len(name) - 1) # => 5
Все это справедливо для любых функций, например, строковых:
name = 'Python'
# Используется интерполяция
print(f'Последний символ: {name[len(name) - 1]}')
# => Последний символ: n
Как вы увидите дальше, выражения можно комбинировать, получая все более сложное поведение в разных местах и любым образом. Чем глубже вы будете изучать Python и практиковаться в нем, тем лучше вы будете понимать работу с выражениями. Со временем вы лучше поймете, как соединять части кода, чтобы получить нужный результат.
Детерминированность
У функций внутри каждого языка программирования есть фундаментальные свойства. Эти свойства помогают прогнозировать поведение функций, способы их тестирования и место использования. К таким свойствам относится детерминированность. Давайте разберемся с детерминированной функцией. Узнаем, зачем эта функция выдает результат, который никак не применяется.
Детерминированная функция
Детерминированная функция возвращает один и тот же результат для одинаковых входных параметров. Например, детерминированной можно назвать функцию, которая считает количество символов:
len('Python') # 6
len('Python') # 6
len('hex') # 3
len('hex') # 3
Можно бесконечно вызывать эту функцию и передавать туда значение 'Python' — она всегда вернет 6.
Посмотрим и обратный случай — недетерминированные функции. Например, к этой категории относится функция, которая возвращает случайное число: у одного и того же входа мы получим всегда разный результат. Если хотя бы один из миллиона вызовов функции вернет другой результат, она считается недетерминированной. Это работает и в том случае, если параметры не принимаются:
# Про синтаксис импортов позже
from random import random
# Функция, которая возвращает случайное число
random() # 0.0432523454325265
random() # 0.2364564577656544
Детерминированность — это важное свойство функции, так как она влияет на многие аспекты. Например, детерминированные функции удобны в работе — их легко оптимизировать и тестировать. Если возможно, то лучше сделать функцию детерминированной.
Для примера рассмотрим одну необычную функцию — она возвращает результат, с которым ничего нельзя сделать.
Побочные эффекты
В Python есть функция print(), которая принимает на вход данные любого типа и выводит их на экран. Она вызывает побочный эффект — из-за выполнения функции запускается действие, которое изменяет среду выполнения. Ещё побочные эффекты вызывают любые сетевые взаимодействия, чтение и запись файлов, вывод информации на экран и печать на принтере. Побочные эффекты — один из основных источников проблем и ошибок в программных системах. Такой код сложнее тестировать, снижается его надежность. При этом без побочных эффектов программирование не имеет смысла. Без них было бы невозможно получить результат работы программы: например, записать в базу, вывести на экран и отправить по сети. Побочными эффектами print() отличается от других функций, которые также принимают на вход данные любого типа. Другие функции возвращают значения, которые можно дальше использовать. В отличие от них, функция print() выводит такой результат, с которым ничего нельзя сделать. Вывод на экран и возврат значения из функции — разные и независимые операции.
Попробуйте сами запустить код в окне ниже с интерпретатором Python и повторите примеры из статьи чтобы самим увидеть и понять как всё это работает. Для этого в ячейке с кодом нажмите клавиши на клавиатуре Shift+Enter или запустите код через кнопку Run по значку ▶.