Что такое функции

Функция — это именованный участок кода. Иначе говоря, мы выделяем какой-то кусок нашего кода и даём ему имя.

Например:

print('Привет!')
# Привет!

Функция print() выводит на экран нашу строку "Привет!". Мы не знаем как она это делает, но мы точно знаем что именно произойдёт.

Вывод: Мы можем использовать чужие функции, не вдаваясь в подробности того, как они работают внутри.

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

# Хотим посчитать цену с НДС для пачки молока
milk_price = 100
vat_rate = 20  # VAT — НДС, 20% — ставка НДС в России.
vat = milk_price * vat_rate / 100  # Налог
milk_price_with_vat = milk_price + vat  # Цена с налогом
print(milk_price_with_vat)  # 120

# А теперь — для пачки макарон
spaghetti_price = 150
vat_rate = 20
vat = spaghetti_price * vat_rate / 100
spaghetti_price_with_vat = spaghetti_price + vat
print(spaghetti_price_with_vat)  # 180

Мы хотим посчитать цену с учётом НДС для двух разных товаров. Для каждого товара мы повторяем одни и те же действия, и в результате получается копипаста. Это проблема:

  1. Если изменится размер НДС, код придётся править уже в двух местах
  2. Если допустили ошибку при расчёте, то её тоже придётся исправлять в двух разных местах
  3. Новой логики не добавляется, а кода становится больше

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

def get_price_with_vat(price):
    vat_rate = 20
    vat = price * vat_rate / 100
    price_with_vat = price + vat
    return price_with_vat

milk_price_vat = get_price_with_vat(100)  # 120
spaghetti_price_vat = get_price_with_vat(150)  # 180

Логика подсчёта цены с НДС написана всего один раз, а мы просто подставляем разные значения.

Теперь давайте посмотрим как написать свою функцию. Разберём get_price_with_vat по частям:

Сигнатура

sample_text

Сигнатура функции пишется в самом начале. Она состоит из:

  1. Ключевого слова def, которое говорит питону о том, что здесь мы начинаем писать новую функцию.
  2. Названия функции.
  3. Параметров, иначе говоря входных данных, необходимых для работы функции.

Параметры функции позволяют применять одну и ту же логику к разным входным данным. В примере с нашей функцией - это цена товара, price. В примере выше мы подставляли цену пачки молока и пачки макарон и получали разные результаты. По сути, параметры - это переменные, которые мы заводим перед тем как написать саму функцию. Мы не можем знать заранее, какое значение придёт в функцию, поэтому мы используем переменную, которая будет хранить входное значение.

Тело функции

sample_text

Здесь всё просто: это тот код, который мы хотим поместить в функцию. Обратите внимание, код тела функции мы пишем с отступом от левого края строки. В питоне принято таким образом помечать какой код относится к функции, а какой — нет. Это правило установлено на уровне языка, поэтому если отступов не сделать — программа сломается. В дальнейшем, вы ещё встретитесь с отступами. Размер одно отступа — 4 пробела.

Есть ещё один нюанс. Всё, что происходит в функции, остаётся внутри неё. Например, все переменные, которые мы создали во время работы функции, окажутся недоступны извне.

def get_price_with_vat(price):
    vat_rate = 20
    vat = price * vat_rate / 100
    price_with_vat = price + vat
    return price_with_vat

get_price_with_vat(100)
print(vat_rate)  # NameError: name 'vat_rate' is not defined

И это логично, ведь нам не нужны промежуточные вычисления, важен только результат. А чтобы результат работы был доступен вне функции, его надо "вернуть".

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

sample_text

Для возврата желаемого значения во внешний мир, используется ключевое слово return:

def get_price_with_vat(price):
    vat_rate = 20
    vat = price * vat_rate / 100
    price_with_vat = price + vat
    return price_with_vat  # price_with_vat равно 120

result = get_price_with_vat(100)
print(result)  # 120

На самом деле, функции всегда возвращают какое-то значение, даже если в ней не написан return. Для таких случаев, в питоне есть специальный тип данных - None, который нужен чтобы описать "тут ничего нет". Сравните с предыдущим примером:

def get_price_with_vat(price):
    vat_rate = 20
    vat = price * vat_rate / 100
    price_with_vat = price + vat
    # тут удалили строку

result = get_price_with_vat(100)
print(result)  # None

Функция len() всегда возвращает длину переданного ей параметра, а функция print() - возвращает None. Из функции можно вернуть несколько значений, для этого перечислить их все через запятую:

def get_vat_and_price_with_vat(price):
    vat_rate = 20
    vat = price * vat_rate / 100
    price_with_vat = price + vat
    return vat, price_with_vat

vat, price = get_vat_and_price_with_vat(100)
print(vat)  # 20
print(price)  # 120

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

def return_interrupt_example():
    print('Это фраза всегда будет печататься на экране')
    somevalue = 1000
    return somevalue
    print('А эта - никогда')

return_interrupt_example()

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

Что ещё почитать