Перейти к содержанию

412 уроков, 25 библиотек и челлендж «Что выведет код?» — бесплатно, код прямо в браузере

Начать обучение
Урок 1 из 20 Начальный 15 мин 100 XP

Функции в Python: первая def

Первая функция: задаём блоку кода имя через def и вызываем по скобкам. Разбираем объявление на части — имя, двоеточие, тело с отступом — и видим, зачем функция вместо копипасты.

Редакция Питоники

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

Что такое функция в Python: коротко

Функция — это блок кода с именем: def имя(): — объявление, имя() — вызов. Тело пишется с отступом в четыре пробела и выполняется только при вызове. Нужна она, чтобы один и тот же код не копировать: правило пишется один раз, а вызовов может быть сколько угодно.

Без функции: копируем строки

Задача: напечатать заголовок чека в рамке — дважды, для двух касс. Без функции решение выглядит как два скопированных куска:

два одинаковых куска кода
print('---')
print('Чек № 1')
print('---')
print()
print('---')
print('Чек № 2')
print('---')
Вывод
---
Чек № 1
---

---
Чек № 2
---

Работает, но куски одинаковые: три строки повторены дважды. Чеков станет десять — придётся скопировать ещё тридцать строк. Захотелось изменить ширину рамки — править каждый кусок отдельно. Такой код медленно читается и легко ломается. Нужен способ записать повтор один раз и дать ему имя.

Первая функция: def

Функция объявляется словом def: за ним идут имя, скобки и двоеточие, а тело — с отступом.

первая функция и два вызова
def print_line():
    print('---')

print_line()
print('Чек № 1')
print_line()
Вывод
---
Чек № 1
---

Читается объявление вслух так: «def print_line — определить блок кода с именем print_line». Разбираем по частям:

  • def — ключевое слово: сообщает Python, что начинается объявление функции;
  • print_line — имя функции: придумываете вы, по правилам имён переменных — латиница, без пробелов;
  • скобки () — место для данных, которые функция примет при вызове; в первой функции данных нет, но сами скобки обязательны;
  • двоеточие в конце строки открывает тело, а тело — строки с отступом 4 пробела, как у цикла for.

Само объявление ничего не печатает. Python прочитал тело, запомнил его под именем print_line и пошёл дальше — тело выполнится только при вызове. Вызов — это имя функции со скобками: print_line(). Скобки здесь — команда «запусти»: без них Python просто видит имя и молчит.

ошибка: имя без скобок
# Так не сработает: имя без скобок — это не вызов
def hello():
    print('Привет!')

hello
Программа завершится молча: hello без скобок — только упоминание имени, тело не запускается. Вызов — hello().
ошибка: тело без отступа
# Так не запускается: print без отступа
def hello():
print('Привет!')
Python ответит IndentationError: expected an indented block. Тело функции, как тело цикла, обязано быть с отступом — по нему Python отличает строки функции от остальных строк программы.

Сначала def, потом вызов

Python читает файл сверху вниз. К моменту вызова функция уже должна быть объявлена — иначе имени ещё не существует. Вызовов может быть сколько угодно:

одна функция, три вызова
def greet():
    print('Добрый день!')

greet()
greet()
greet()
Вывод
Добрый день!
Добрый день!
Добрый день!

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

ошибка: вызов раньше объявления
# Так не запускается: вызов до def
greet()

def greet():
    print('Добрый день!')
Python ответит NameError: name 'greet' is not defined. На первой строке файл прочитан не до конца — имени greet ещё не существует. Сначала def, потом вызов.

Функция и цикл: два инструмента вместе

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

цикл вызывает функцию
def print_divider():
    print('----------')

for i in [1, 2, 3]:
    print('Шаг', i)
    print_divider()
Вывод
Шаг 1
----------
Шаг 2
----------
Шаг 3
----------

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

Зачем функция вместо копипасты

КопипастаФункция
Повтор записан в каждом местеПовтор записан один раз под именем
Правка — в каждой копииПравка — в одном теле функции
Имени у повтора нет — читается как набор строкИмя объясняет, что делает кусок
Кусок отдельно не запуститьФункция вызывается и проверяется отдельно

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

меню как функция
def show_menu():
    print('1 — начать игру')
    print('2 — настройки')
    print('0 — выход')

show_menu()
print('Введите номер пункта:')
Вывод
1 — начать игру
2 — настройки
0 — выход
Введите номер пункта:
  • шапки, подвалы и разделители отчётов — печать одинаковых рамок одним вызовом;
  • меню программы: пункты нужны в нескольких местах — вызовом одной функции;
  • повторяющиеся куски тела цикла: вынесите их в функцию с именем и вызывайте из цикла — так делают в уроках про циклы, когда тело перестаёт помещаться в одну строку.

Имя функции — часть кода

Имя функции читают чаще, чем её тело. Открывая файл, человек сперва ищет в коде print_divider, а не три строки с print. Имя — короткое описание того, что делает блок, и экономия на нём выходит боком: f1, do_it, func не говорят ничего, и через месяц никто не вспомнит, что там было. Мы держимся правила: имя начинается с глагола и читается как команда — print_divider, show_menu, count_words. Два слова пишутся через подчёркивание, как принято в Python: print_divider, а не printDivider.

ИмяЧто подразумеваетКак читается в коде
print_dividerнапечатать разделительprint_divider() — напечатать разделитель
show_menuпоказать менюshow_menu() — показать меню
count_wordsпосчитать словаcount_words() — посчитать слова
f1, do_it, funcничегоf1() — что? придётся лезть в тело

Побочный эффект хорошего имени — Python сам подсказывает, где ошибка. Вызвали несуществующую функцию — получите NameError с точным именем в тексте: опечатка в print_divider видна сразу, читаешь и правишь. Имя — не украшение, а диагностика.

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

В файле с десятком функций рано или поздно возникает соблазн: поставить вызов туда, где он «по смыслу» подходит, — и разорвать файл на две части. Потом выясняется, что половина вызовов стоит выше объявлений, и при запуске программа падает с NameError. Мы держимся простого порядка: сначала все определения, потом работа. Читается как оглавление: сначала что есть, потом что с этим делают.

сначала определения, потом вызовы
def print_divider():
    print('----------')


def show_title():
    print('Отчёт за неделю')


show_title()
print_divider()
Вывод
Отчёт за неделю
----------

Функция, которая печатает, но не возвращает

Ещё одну вещь стоит увидеть сразу. Функция, внутри которой только print, ничего не возвращает: попросите у неё результат — получите None. Python не ругается, потому что запрета на None нет, но и пользы от такой функции нет: её вывод никуда не передать, кроме экрана.

печать вместо возврата
def show_menu():
    print('1 — начать игру')
    print('0 — выход')

result = show_menu()
print('Функция вернула:', result)
Вывод
1 — начать игру
0 — выход
Функция вернула: None

Это не ошибка, а молчаливое «не знаю». Отсюда рабочее правило нашей команды: функция возвращает значение, а печатает тот, кто её вызывает. Разница между «напечатать» и «вернуть» — тема урока про return.

Частые ошибки новичка

ОшибкаЧто скажет PythonКак правильно
Забыли скобки при вызовеНичего — программа отработает молчаprint_line()
Вызов стоит выше объявленияNameError: name ... is not definedСначала def, потом вызов
Нет двоеточия в заголовкеSyntaxError: invalid syntaxdef print_line():
Тело без отступаIndentationError: expected an indented blockСдвиг на 4 пробела
Опечатка в имениNameError: name 'print_lien' is not definedСверьте имя с объявлением

Первая строка таблицы — единственная, где Python не поможет: пустой вывод выглядит как «программа отработала и всё в порядке». Если скрипт завершился мгновенно и на экране ничего нет, первым делом проверьте скобки у вызовов.

Первая функция объявлена и вызвана. Но она каждый раз делает одно и то же — данных у неё нет. Настоящая сила начинается, когда функция принимает данные: одна функция приветствия для разных гостей, одна печать цены для разных товаров. Как передать данные внутрь — тема следующего урока, а отдача результата наружу — урок про return.

Что выведет код?

Сначала предскажи ответ в голове — это главный навык программиста.

def hi():
    print('привет')

hi()
hi()
def f():
    print('А')
    print('Б')

f()
def run():
    print('старт')

run
Проверь себя
0 / 8

1. Что делает строка def print_line():?

2. Как правильно вызвать функцию print_line?

3. Когда выполняется тело функции?

4. Что произойдёт при вызове функции раньше её объявления?

5. Функция print_line печатает одну строку из дефисов. Сколько строк напечатают три вызова print_line()?

6. Что обязательно стоит после имени функции в объявлении?

7. Что вернёт выражение result = show_menu(), если внутри функции только print?

8. Почему в файле сначала пишут все определения функций, а вызовы оставляют на конец?

Карточки терминов
Запомнено: 0 / 8
Практика

Объяви функцию show_banner, которая печатает три строки: «*», «Меню дня», «*». Вызови её два раза.

practice.py
Вопросы и ответы по уроку

Как создать функцию в Python?

Ключевым словом def: def имя(): — скобки и двоеточие обязательны, тело пишется с отступом 4 пробела под заголовком. Создание только запоминает код; выполнить его можно вызовом: имя().

Урок 2: аргументы функции

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

Потому что def — это объявление, а не вызов: Python запоминает тело под именем и идёт дальше. Тело выполняется при каждом вызове со скобками; объявление без вызова не печатает и не считает ничего.

Можно ли вызвать функцию до её объявления?

Нет: Python читает файл сверху вниз, и к строке вызова имя ещё не существует — будет NameError: name ... is not defined. Сначала def, потом вызов; вызовы в теле других функций считаются позже, при их запуске.

Чем функция отличается от цикла?

Цикл повторяет тело для каждого элемента списка — сам запускает повтор. Функция даёт блоку кода имя и запускается только по вызову. Они дополняют друг друга: функция хранит повтор в одном месте, цикл — запускает его много раз.

Как правильно назвать функцию в Python?

Имя должно читаться как команда и начинаться с глагола: print_divider, show_menu, count_words. Два слова разделяют подчёркиванием — так принято в Python. Имена f1, do_it и func ничего не сообщают читателю: он не знает, что делает блок, пока не откроет тело.

Функция напечатала текст, но в переменную ничего не попало. Почему?

Потому что print пишет на экран, а return отдаёт значение программе. Функция, в которой есть только print, возвращает None. Правило рабочей команды: функция возвращает значение, а печатает вызывающий код.

Программа запустилась, но ничего не напечатала и ошибок не было. Что проверить?

Скобки у вызова. Python считает имя функции без скобок упоминанием, а не запуском, и молча идёт дальше — это единственная ошибка, о которой интерпретатор не предупреждает. Дальше по порядку: правильно ли написано имя и не стоит ли вызов выше объявления функции.

Понравился урок? Сошлитесь на него

«Функция — это блок кода с именем: определили один раз — вызываете сколько угодно.»

Скопируйте готовую ссылку в формате HTML, Markdown или чистый адрес и вставьте в статью на Habr, VC, Telegram-канал или свой блог — так о проекте узнают новые читатели.

TelegramVK

Что дальше

Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.

Похожие уроки по темам

Подобраны автоматически по пересечению тем и ключевых слов.