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

Pythonобновлено 07.10.20269 мин чтенияесть тренажёр

Функции в Python позволяют дать имя куску кода и запускать его сколько угодно раз одной строкой. Вы уже пользовались готовыми — print, len, input, — а теперь научитесь писать свои: с параметрами, возвратом результата и значениями по умолчанию. В конце страницы — 6 задач с автопроверкой.

Загружаем…

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

Функция — это именованный блок кода, который выполняет одну задачу и запускается по имени. Сначала функцию объявляют словом def, а потом вызывают, написав имя и круглые скобки.

def hello():
    print("Привет!")
    print("Я — функция.")

hello()
hello()
Привет!
Я — функция.
Привет!
Я — функция.

Строки с def по последний отступ — это объявление: Python запоминает функцию, но ничего не выполняет. Код внутри запускается только при вызове hello(). Два вызова — два повтора. Если убрать скобки и написать просто hello, функция не выполнится: без скобок это лишь ссылка на неё.

Вы уже знаете много встроенных функций в Python: print() выводит текст, len() считает длину, int() превращает строку в число. Свои функции в Python устроены так же, просто их придумываете вы, и ограничений на их число нет. В Scratch похожую роль играют собственные блоки, которые создают кнопкой «Создать блок»: собрали скрипт, дали ему имя и вызываете где угодно. По федеральной образовательной программе вспомогательные алгоритмы изучают в 9 классе[1], а в Python они записываются именно как функции.

Как объявить функцию: def, имя и тело

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

def draw_line(length):
    print("-" * length)

draw_line(10)
print("Заголовок")
draw_line(10)

Имя функции подчиняется тем же правилам, что и имя переменной: латинские буквы, цифры и подчёркивание, не с цифры. Руководство PEP 8 рекомендует писать имена функций строчными буквами через подчёркивание — draw_line, count_vowels[2]. Хорошее имя функции — глагол, который говорит, что она делает: draw, calc_area, is_even. Функцию нужно объявить раньше, чем вызвать: Python читает файл сверху вниз, и вызов до def закончится ошибкой NameError.

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

Параметры и аргументы функции в Python

Параметры — это переменные в скобках при объявлении функции, а аргументы — значения, которые передают при вызове. При вызове draw_line(10) параметр length получает аргумент 10.

def introduce(name, age):
    print("Меня зовут", name, "и мне", age, "лет")

introduce("Тимур", 11)
introduce("Лиза", 12)
introduce(age=10, name="Макс")

Аргументы раздаются параметрам по порядку: первый — первому, второй — второму. Если перепутать порядок, программа не упадёт, но скажет «Меня зовут 11». Чтобы не зависеть от порядка, аргументы можно передавать по имени: introduce(age=10, name="Макс"). Количество аргументов должно совпадать с числом параметров — иначе Python выдаст TypeError с текстом про missing или takes positional arguments. Разбор этой ошибки — на странице об ошибке TypeError.

Команда return: функция возвращает результат

Команда return завершает функцию и отдаёт значение туда, где её вызвали. Это главное отличие от print: print только показывает текст на экране, а return передаёт результат, с которым программа может работать дальше.

def square(x):
    return x * x

a = square(4)
b = square(3) + square(2)
print(a, b)
print(square(square(2)))
16 13
16
Что сравниваемprint внутри функцииreturn в функции
Куда идёт результатНа экранВ место вызова
Можно сохранить в переменнуюНет, будет NoneДа
Можно использовать в выраженииНетДа: square(3) + 1
Что после командыФункция продолжает работуФункция сразу заканчивается

Если в функции нет return или он написан без значения, она возвращает специальное значение None. Это правило функции в Python соблюдают всегда, даже встроенные. Поэтому x = print("hi") кладёт в x именно None. Return может стоять в нескольких местах, например в разных ветках if: какой сработает первым, тот и завершит функцию. Функции, которые возвращают результат, легко проверять и соединять между собой, — так строят большие программы из маленьких деталей. Официальная документация Python описывает return в разделе об определении функций[3].

Значения параметров по умолчанию

Если у параметра есть значение по умолчанию, при вызове его можно не указывать: запись def greet(name, word="Привет") позволяет вызвать функцию и с 1, и с 2 аргументами.

def greet(name, word="Привет"):
    return word + ", " + name + "!"

print(greet("Оля"))
print(greet("Оля", "Здравствуй"))

def power(base, exp=2):
    return base ** exp

print(power(5), power(2, 10))

Параметры функции со значением по умолчанию пишут после обычных, и по-другому не получится: def greet(word="Привет", name) — синтаксическая ошибка. Встроенные функции тоже так устроены: у print есть параметры sep=" " и end="\n", поэтому мы их обычно не указываем. В качестве значения по умолчанию безопасно использовать числа, строки, True, False и None. Пустой список [] в этой роли — известная ловушка: он создаётся один раз и копит изменения между вызовами.

Область видимости: локальные и глобальные переменные

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

bonus = 5

def add_bonus(score):
    result = score + bonus
    return result

print(add_bonus(10))
print(bonus)

Если после этого написать print(result) вне функции, будет NameError — так область видимости описана и в документации Python: переменная result жила только внутри вызова. Это удобно — у каждой функции свои «черновики», и одинаковые имена в разных функциях не мешают друг другу. Менять глобальные переменные изнутри можно через слово global, но в учебных программах лучше этого избегать: передайте значение параметром и верните результат через return. Ошибки с невидимыми переменными разобраны на странице об ошибке NameError.

Зачем нужны свои подпрограммы

Свои подпрограммы решают 3 задачи: убирают повторы кода, разбивают большую программу на понятные части и позволяют проверить каждую часть отдельно. Разбиение задачи на подзадачи — один из приёмов вычислительного мышления.

Представьте игру, где после каждого раунда нужно вывести счёт, проверить победу и нарисовать рамку. Без подпрограмм эти 15 строк повторятся в коде трижды, а исправлять ошибку придётся в трёх местах. С блоками show_score(), check_win() и draw_frame() основная программа читается как план: что происходит и в каком порядке. Jeannette Wing в статье о вычислительном мышлении описывает абстракцию и декомпозицию как приёмы, которыми решают большие сложные задачи[4]: вы думаете о том, что делает блок, а не о том, как она устроена внутри. Подробнее об этих приёмах — в статье про вычислительное мышление.

Задачи с автопроверкой

Чтобы закрепить тему, решите 6 задач в тренажёре вверху страницы: в каждой уже есть заготовка с заголовком, нужно написать тело. Нажмите «✓ Проверить» — программа запустит решение на тестах и покажет «Ожидалось» и «Получилось».

Задачи идут от одной строки с возвратом значения к решениям с условиями, циклом и значениями по умолчанию. Если застряли, нажмите «Подсказка»; «Показать решение» открывайте только после своих попыток. Решать с перерывами в несколько дней полезнее, чем всё за один вечер: эффект распределённой практики описан в обзоре Cepeda и соавторов[5]. Больше упражнений — площадь, НОД, простые числа — в подборке задач на функции.

Когда своя подпрограмма не нужна

Своя подпрограмма не нужна, если код выполняется один раз, занимает пару строк или в языке уже есть готовый инструмент с тем же действием. В этих 4 случаях лишняя обёртка только мешает читать программу.

  • Действие встречается 1 раз и занимает 2 строки. Обёртка добавит ещё 2 строки и прыжок глазами по коду.
  • Нужна сумма списка из 10 чисел. Встроенная sum() уже делает это, писать свою незачем.
  • Функция в 50 строк делает 5 разных дел. Её лучше разделить на несколько маленьких, каждая — с одной задачей.
  • Первая программа на 5 строк. Новичку сначала важно понять print, input и переменные, собственные блоки подождут.

«Функция обязательно должна что-то выводить на экран». Это миф: многие полезные подпрограммы ничего не печатают, а только отдают результат в место вызова.

«Переменная, созданная внутри def, видна во всей программе». Это не подтверждается: после завершения вызова локальная переменная исчезает, и обращение к ней снаружи вызывает NameError.

Чего делать нельзя

Нельзя вызывать подпрограмму раньше, чем она объявлена, — Python читает файл сверху вниз. Остальные правила касаются того, как она получает и отдаёт данные.

  • Нельзя путать вывод на экран и возврат значения: если результат нужен дальше в программе, его надо вернуть, а не напечатать.
  • Не следует забывать скобки при вызове: hello без () ничего не запустит.
  • Не стоит давать своему блоку имя встроенного — sum или list: после этого стандартные версии перестанут работать.
  • Не допускается ставить параметр без значения после параметра со значением по умолчанию — будет SyntaxError.
  • Не стоит использовать изменяемый список как значение по умолчанию: он сохраняет изменения между вызовами.
  • Нельзя писать код после возврата значения в той же ветке и ждать, что он выполнится, — подпрограмма к этому моменту уже закончилась.

Источники

[1] Приказ Минпросвещения России от 18.05.2023 № 370 «Об утверждении федеральной образовательной программы основного общего образования».

[2] van Rossum G., Warsaw B., Coghlan N. PEP 8 — Style Guide for Python Code. Python Software Foundation, 2001.

[3] The Python Tutorial (официальная документация Python 3). Python Software Foundation.

[4] Wing J. M. Computational thinking // Communications of the ACM. 2006. Vol. 49, № 3. P. 33–35.

[5] Cepeda N. J., Pashler H., Vul E., Wixted J. T., Rohrer D. Distributed practice in verbal recall tasks: A review and quantitative synthesis // Psychological Bulletin. 2006. Vol. 132, № 3. P. 354–380.

Вопросы и ответы

Сколько параметров можно объявить?

Сколько угодно, в том числе ни одного. Но если их больше 4–5, код становится трудно читать — возможно, стоит разделить задачу на части.

Можно ли вернуть сразу два значения?

Да: запись через запятую после возврата отдаёт пару, а при вызове её можно разложить по двум переменным: x, y = f().

Чем метод отличается от обычной подпрограммы?

Метод вызывается через точку у конкретного объекта, например "кот".upper(). Обычную подпрограмму вызывают просто по имени, как len("кот").

Можно ли вызывать одну подпрограмму из другой?

Конечно, так и строят программы: один блок использует результаты других. Он может вызывать даже сам себя — это называется рекурсией, но новичкам с ней лучше подождать.

Где писать объявления в файле?

Принято собирать все объявления в начале файла, после строк с import, а основной код — ниже. Так программу легче читать.

Что значит None в выводе?

Так Python показывает «ничего». Чаще всего None появляется, когда печатают результат подпрограммы, в которой забыли вернуть значение.