Функции в 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
# Так не запускается: print без отступа
def hello():
print('Привет!')
Сначала def, потом вызов
Python читает файл сверху вниз. К моменту вызова функция уже должна быть объявлена — иначе имени ещё не существует. Вызовов может быть сколько угодно:
def greet():
print('Добрый день!')
greet()
greet()
greet()
Добрый день! Добрый день! Добрый день!
Три вызова — три выполнения тела. Ставить вызовы можно где угодно ниже объявления: в цикле, в условии, из другой функции.
# Так не запускается: вызов до def
greet()
def greet():
print('Добрый день!')
Функция и цикл: два инструмента вместе
Функция и цикл решают разные задачи повторов. Цикл повторяет тело для каждого элемента списка, функция даёт повтору имя и хранит его в одном месте. Вместе они закрывают двойной повтор: цикл отвечает за «для каждого», функция — за «как именно»:
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 syntax | def 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
1. Что делает строка def print_line():?
2. Как правильно вызвать функцию print_line?
3. Когда выполняется тело функции?
4. Что произойдёт при вызове функции раньше её объявления?
5. Функция print_line печатает одну строку из дефисов. Сколько строк напечатают три вызова print_line()?
6. Что обязательно стоит после имени функции в объявлении?
7. Что вернёт выражение result = show_menu(), если внутри функции только print?
8. Почему в файле сначала пишут все определения функций, а вызовы оставляют на конец?
Объяви функцию show_banner, которая печатает три строки: «*», «Меню дня», «*». Вызови её два раза.
Как создать функцию в 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-канал или свой блог — так о проекте узнают новые читатели.
Что дальше
Осталось в разделе: 20 из 20. Прогресс хранится в вашем браузере.
Что читать дальше
Функции · Урок 2
Аргументы функции в Python: данные внутрь
Функция принимает данные через параметры: greet('Анна') здоровается с Анной. Разбираем позиционные аргументы, порядок и количество — и типичную ошибку TypeError.
Функции · Урок 3
Return в Python: функция возвращает результат
print показывает значение человеку, return отдаёт программе. Учимся возвращать результат, класть его в переменную и использовать в выражениях — и не путать return с print.
Циклы · Урок 1
Цикл for в Python: первый цикл
Первый цикл for: компьютер повторяет одну строку за вас. Перебираем список, разбираем переменную цикла и тело с отступами — и видим, зачем цикл вместо копипасты.
Похожие уроки по темам
Подобраны автоматически по пересечению тем и ключевых слов.
asyncio · Урок 2
Первая корутина: async def и await
async def — функция с паузами, await — «дождись результата». Звучит просто, пока не выясняется, что вызов async-функции не выполняет её тело. Разбираем оба ключевых слова на живом коде.
вызов корутины без awaitасинхронные функции python
openpyxl · Урок 1
Excel на Python: первая книга xlsx через openpyxl
Первая книга xlsx из кода: Workbook, запись в ячейки и wb.save — настоящий Excel-файл создаётся прямо в браузере, без установленного Excel.
создать excel pythonсоздать excel файл python
Функции · Урок 13
Функция как значение в Python: передача функций
map и sorted уже принимали функции в аргументах — теперь разберём приём целиком: функция такое же значение, как число или строка.
функции высшего порядка pythonpython передать функцию в функцию