Функции в Python: как создать через def, вызвать и вернуть результат

Функцию в Python создают словом def: имя, параметры в скобках, двоеточие и тело с отступом.

В статье вызов и return, виды аргументов, *args и **kwargs, область видимости, lambda, чистые функции и шесть частых ошибок с текстом сообщения и решением. Каждый пример дан с выводом.

Статью написал:
Ваня Буявец, продюсер, основатель Checkroi
Ваня Буявец
Основатель Checkroi, продюсер, эксперт в выборе онлайн-курсов
Все 2967 статей автора Подписаться на Телеграм-канал
Одобрено экспертом:
Наташа Буявец, основатель Checkroi, эксперт по онлайн-курсам
Наташа Буявец
Основательница Checkroi, продюсер Youtube-каналов, эксперт по онлайн-курсам
Все 3621 экспертное мнение Подписаться на Телеграм-канал
Обложка: Функции в Python: как создать через def, вызвать и вернуть результат

Функция в Python создаётся словом def: после него пишут имя, в скобках параметры, ставят двоеточие и с отступом пишут тело. Результат функция отдаёт через return, а запускается вызовом по имени со скобками: greet("Аня").

def greet(name):
    return f"Привет, {name}!"

message = greet("Аня")
print(message)
# Привет, Аня!

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

CheckroiCheckroiПодборка курсов по Python566 курсов • 51 школаСравните цены, школы, программу и найдите выгодные предложения по обучениюСравнить→

Как создать функцию через def

Рой-программист собирает функцию из блоков кода за ноутбуком

Синтаксис описан в учебнике на docs.python.org: за def идут имя и список параметров в скобках, а тело начинается со следующей строки и обязано быть с отступом.

  1. Напишите def и имя функции: def area.
  2. В скобках перечислите параметры через запятую: (width, height). Параметров может не быть, тогда скобки пустые.
  3. Поставьте двоеточие в конце строки.
  4. С новой строки и с отступом в четыре пробела напишите тело: что функция делает с данными.
  5. Если функция должна что-то отдать наружу, допишите return и выражение.

Код удобнее писать не в интерактивной консоли, а в файле: как создать его и запустить одной кнопкой, показано в инструкции про файл Python в VS Code.

def area(width, height):
    return width * height

print(area(5, 4))
# 20

Имя пишите строчными буквами через подчёркивание: calculate_total, а не CalculateTotal. Так советует PEP 8, руководство по стилю кода Python.

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

Как вызвать функцию

Чтобы вызвать функцию, напишите её имя и круглые скобки, в скобках аргументы. Без скобок вы получите не результат, а саму функцию как объект:

print(area(5, 4))
# 20
print(area)
# <function area at 0x1060a7270>

Адрес в конце у вас будет другим, это место в памяти. Если в выводе появилось <function …>, значит, где-то забыли скобки.

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

print(hello())

def hello():
    return "hi"

# NameError: name 'hello' is not defined. Did you mean: 'help'?

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

Канал основателя Checkroi Вани Буявца3 700 человек читают мой Телеграм-канал про нейросетиСобрал промпты для Claude Code и ChatGPT, разборы ИИ-инструментов и лайфхаки по продвижению бизнеса в одном местеПрисоединиться

Что делает return и чем он отличается от print

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

def add_print(a, b):
    print(a + b)

def add_return(a, b):
    return a + b

x = add_print(2, 3)
y = add_return(2, 3)
print(x, y)
# 5
# None 5

Первая функция напечатала пятёрку, но в переменную x попал None. С таким значением дальше ничего не посчитать. Если результат нужен в программе, пишите return, а print оставьте для вывода пользователю.

Функция без return и «процедуры»

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

Заготовку функции, которую допишете потом, оформляют через pass:

def todo():
    pass

print(todo())
# None

Несколько значений и ранний выход

Через запятую return отдаёт несколько значений сразу. На деле это один кортеж, который удобно разложить по переменным:

def min_max(numbers):
    return min(numbers), max(numbers)

low, high = min_max([7, 2, 9, 4])
print(low, high)
# 2 9
print(min_max([7, 2, 9, 4]))
# (2, 9)

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

def check_age(age):
    if age < 0:
        return "Возраст не может быть отрицательным"
    if age < 18:
        return "Доступ закрыт"
    return "Добро пожаловать"

print(check_age(-3))
print(check_age(15))
print(check_age(30))
# Возраст не может быть отрицательным
# Доступ закрыт
# Добро пожаловать

Короткую проверку из двух веток можно уложить и в одну строку, об этом в разборе тернарного оператора в Python.

Параметры и аргументы

Эти два слова часто смешивают. Параметр — имя в скобках при определении (width). Аргументом называют значение, которое вы передаёте при вызове (5).

Вид Как выглядит Когда нужен
Позиционный area(5, 4) Значения встают в параметры по порядку
Именованный area(height=4, width=5) Порядок не важен, вызов читается без подсказок
Со значением по умолчанию def f(price, discount=10) Аргумент можно не передавать
*args def total(*numbers) Заранее неизвестно, сколько позиционных аргументов придёт
**kwargs def profile(**data) Заранее неизвестно, сколько именованных аргументов придёт

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

def price_with_discount(price, discount=10):
    return price - price * discount / 100

print(price_with_discount(2000))
print(price_with_discount(2000, 25))
print(price_with_discount(discount=5, price=1000))
# 1800.0
# 1500.0
# 950.0

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

*args и **kwargs

Звёздочка собирает лишние позиционные аргументы в кортеж, две звёздочки собирают именованные в словарь:

def total(*numbers):
    print(numbers)
    return sum(numbers)

print(total(1, 2, 3))
# (1, 2, 3)
# 6

def profile(**data):
    print(data)

profile(name="Аня", city="Казань")
# {'name': 'Аня', 'city': 'Казань'}

Имена args и kwargs условные, работают именно звёздочки. Другие способы сложить числа из списка, от цикла до NumPy, есть в статье как суммировать список в Python.

Только позиционные и только именованные

Косая черта / в списке параметров запрещает передавать стоящие до неё параметры по имени, звёздочка * требует передавать стоящие после неё только по имени. Первое появилось в Python 3.8 по PEP 570, второе описано в PEP 3102.

def power(base, exp=2, /, *, verbose=False):
    result = base ** exp
    if verbose:
        print(f"{base} в степени {exp} = {result}")
    return result

print(power(3))
power(2, 10, verbose=True)
print(power(2, 3, True))
# 9
# 2 в степени 10 = 1024
# TypeError: power() takes from 1 to 2 positional arguments but 3 were given

Две звёздочки в base ** exp к параметрам отношения не имеют, это возведение в степень, о нём в статье про операторы в Python.

Зачем это нужно: флаг вроде verbose в вызове power(2, 3, True) непонятен без заглядывания в определение. Звёздочка заставляет писать verbose=True, и код читается сам.

Где живут переменные: локальная и глобальная область

Переменная, созданная внутри функции, видна только там. Обратное правило хитрее. В FAQ по программированию оно сформулировано так: если переменную внутри функции только читают, она считается глобальной. Если ей где-то в теле присваивают значение, она локальная.

Отсюда самая частая ошибка новичка со счётчиком:

counter = 0

def increase():
    counter += 1

increase()
# UnboundLocalError: cannot access local variable 'counter' where it is not associated with a value

Из-за += Python решил, что counter локальная, а значения у неё внутри функции ещё нет.

Решение: передать значение аргументом и вернуть новое через return.

counter = 0

def increase(value):
    return value + 1

counter = increase(counter)
print(counter)
# 1

Есть и слово global counter в начале тела, оно разрешает менять глобальную переменную. Работает, но такие функции трудно проверять: результат зависит от того, что лежит снаружи. Для вложенных функций есть nonlocal, он меняет переменную объемлющей функции:

def make_counter():
    count = 0
    def step():
        nonlocal count
        count += 1
        return count
    return step

tick = make_counter()
tick()
print(tick())
# 2

Lambda и передача кода как значения

Функция в Python тоже объект. Её можно положить в переменную, передать в другую функцию, вернуть из функции, как make_counter выше:

def shout(text):
    return text.upper() + "!"

action = shout
print(action("готово"))
print(list(map(shout, ["да", "нет"])))
# ГОТОВО!
# ['ДА!', 'НЕТ!']

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

square = lambda x: x * x
print(square(6))
# 36

words = ["яблоко", "кот", "банан"]
print(sorted(words, key=len))
print(sorted(words, key=lambda w: w[-1]))
# ['кот', 'банан', 'яблоко']
# ['банан', 'яблоко', 'кот']

Лямбду чаще всего встречают в параметре key у сортировки: она говорит, по какому признаку сравнивать элементы. Подробнее в статье про метод sort() и функцию sorted().

Присваивать лямбду переменной, как square выше, PEP 8 не одобряет: он требует в таком случае всегда писать def.

Ваня БуявецКанал основателя Checkroi Вани БуявцаЗабирайте промпты и обучение по нейросетям в моём Телеграм-каналеБольше 3 700 человек уже применяют Claude Code, ChatGPT и другие нейросети в работе, учёбе, бизнесе и жизниПерейти в канал

Чистые функции и побочные эффекты

Три коробки-модуля передают друг другу данные по ленте

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

cart = []

def add_impure(item):
    cart.append(item)

def add_pure(items, item):
    return items + [item]

add_impure("чай")
print(cart)
# ['чай']

old = ["чай"]
new = add_pure(old, "сахар")
print(old, new)
# ['чай'] ['чай', 'сахар']

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

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

Пример: разбить программу на функции

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

def parse_scores(line):
    return [int(x) for x in line.split()]

def average(numbers):
    return sum(numbers) / len(numbers)

def grade(avg):
    if avg >= 4.5:
        return "отлично"
    if avg >= 3.5:
        return "хорошо"
    return "надо подтянуть"

def report(line):
    scores = parse_scores(line)
    avg = average(scores)
    return f"Средний балл {avg:.2f}: {grade(avg)}"

print(report("5 4 5 5 3"))
print(report("3 4 3"))
# Средний балл 4.40: хорошо
# Средний балл 3.33: надо подтянуть

Поменялись пороги оценок, и вы правите только grade. Оценки стали приходить из файла, а не строкой? Меняется только parse_scores. Остальной код об этом не знает. Потренироваться в таком разбиении можно на блоке про функции в подборке 30 задач по Python для начинающих.

Одна подсказка к названиям: называйте функцию глаголом или тем, что она вернёт. average, parse_scores, is_valid читаются без комментариев, а func1 и do_stuff заставляют лезть в тело.

Docstring, подсказки типов и рекурсия

Строка документации

Первая строка в теле, взятая в тройные кавычки, становится документацией функции. Её показывают help() и подсказки редактора. PEP 257 советует писать её как команду («Вернуть площадь…») и заканчивать точкой.

Подсказки типов

После параметра через двоеточие можно указать ожидаемый тип, после скобок через -> указывают тип результата. Python эти подсказки при запуске не проверяет: авторы PEP 484 прямо пишут, что язык останется динамически типизированным. Ловят несоответствия редактор и анализаторы вроде mypy.

def area(width: float, height: float) -> float:
    """Вернуть площадь прямоугольника."""
    return width * height

print(area.__doc__)
print(area("ab", 3))
# Вернуть площадь прямоугольника.
# ababab

Строку умножили на три, и никакой ошибки: подсказка float ничего не запретила.

Рекурсия

Функция может вызывать сама себя. Нужно условие остановки, иначе вызовы не кончатся:

def factorial(n):
    if n <= 1:
        return 1
    return n * factorial(n - 1)

print(factorial(5))
# 120

import sys
print(sys.getrecursionlimit())
# 1000

Глубина ограничена, текущий предел показывает sys.getrecursionlimit(). Для обхода больших данных надёжнее обычный цикл, например while или for.

Что уже встроено в Python

Прежде чем писать свою функцию, проверьте, нет ли готовой. В таблице встроенных функций на docs.python.org 73 имени, они доступны без импорта. Часть из них формально типы (int, list, str), но вызываются так же.

  • длина, сумма, наименьшее и наибольшее: len(), sum(), min(), max();
  • работа с последовательностями: sorted(), reversed(), enumerate(), zip();
  • ввод, вывод и файлы: input(), print(), open();
  • применить функцию к каждому элементу или проверить условие: map(), filter(), any(), all().

Знаки вроде //, % и ** функциями не являются, это операторы. А функции, которые принадлежат объекту и вызываются через точку (words.append()), называются методами, они появятся вместе с классами в разборе ООП простыми словами.

Частые ошибки и как их исправить

Рой радуется исправленной ошибке в коде на мониторе

Большинство ошибок с функциями узнаётся по тексту сообщения. Найдите своё в левой колонке.

Что видите Почему Что сделать
<function … at 0x…> вместо результата Функцию упомянули без скобок Дописать скобки: area()
None там, где ждали число В функции print вместо return Вернуть значение через return
IndentationError: expected an indented block after function definition Тело функции без отступа Сдвинуть тело на четыре пробела
TypeError: area() missing 1 required positional argument: 'height' Передали меньше аргументов, чем параметров Передать все или задать значение по умолчанию
NameError: name '…' is not defined Вызов стоит выше def или в имени опечатка Перенести определение выше, сверить имя
UnboundLocalError Глобальную переменную меняют внутри функции Передать аргументом и вернуть через return

Изменяемое значение по умолчанию

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

def items_to_list(item, basket=[]):
    basket.append(item)
    return basket

print(items_to_list("хлеб"))
print(items_to_list("молоко"))
# ['хлеб']
# ['хлеб', 'молоко']

Ждали два списка по одному товару, а получили общий. Поведение описано в FAQ на docs.python.org: значение по умолчанию вычисляется один раз.

Решение: по умолчанию ставить None и создавать список внутри функции.

def items_to_list_fixed(item, basket=None):
    if basket is None:
        basket = []
    basket.append(item)
    return basket

print(items_to_list_fixed("хлеб"))
print(items_to_list_fixed("молоко"))
# ['хлеб']
# ['молоко']

То же касается словарей и множеств. Чем отличаются append(), insert() и extend(), показано в статье как добавить элемент в список Python.

Как закрепить

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

Где освоить Python системно

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

Если думаете о Python как о профессии, начните с обзора кто такой Python-разработчик и чем он занимается. Ниже пять программ из каталога.

КурсШколаСтоимость со скидкойВ рассрочкуДлитель­ностьОбзор курса от Checkroi
Профессия «Python-разработчик»
Перейти на сайт курса
SkillboxSkillbox157 335 ₽5987 ₽/мес.10 месяцевОбзор курса
Fullstack-разработчик на Python
Перейти на сайт курса
НетологияНетология137 011 ₽7125 ₽/мес.21 месяцОбзор курса
ДО Профессия Python-разработчик
Перейти на сайт курса
GeekBrainsGeekBrains149 001 ₽3167 ₽/мес.10 месяцевОбзор курса
Автоматизированное тестирование на Python
Перейти на сайт курса
SkillboxSkillbox118 666 ₽4108 ₽/мес.9 месяцевОбзор курса
Программирование на Python ПРО
Перейти на сайт курса
SkillboxSkillbox119 600 ₽ - 17 месяцевОбзор курса

Больше программ — в полном каталоге курсов по Python

Часто задаваемые вопросы

Что такое def в Python?

Это ключевое слово, с которого начинается определение функции. После def пишут имя, параметры в скобках и двоеточие, а тело функции пишут с новой строки с отступом. Сама строка с def функцию не запускает, тело выполнится при вызове.

Как вызвать функцию в Python?

Написать её имя и круглые скобки с аргументами: area(5, 4). Без скобок вы получите сам объект функции, а не результат. Вызов должен стоять ниже строки с def, иначе Python выдаст NameError.

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

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

Можно ли вернуть из функции несколько значений?

Да, перечислите их через запятую: return low, high. Python упакует их в кортеж, а при вызове его можно разложить по переменным: low, high = min_max(numbers).

Что такое *args и **kwargs?

Это способ принять заранее неизвестное число аргументов. Одна звёздочка собирает лишние позиционные аргументы в кортеж, две звёздочки собирают именованные в словарь. Имена args и kwargs условные, работают именно звёздочки.

Сколько встроенных функций в Python?

В таблице встроенных функций на docs.python.org 73 имени: len, print, sum, sorted, input и другие. Они доступны без импорта, часть из них формально типы, например int и list.

Читайте Checkroi первым в Google
Добавьте Checkroi в избранные источники — и наши разборы курсов и обзоры школ будут показываться выше в вашей выдаче Google.
Оставить комментарий
0 комментариев
Форма комментария

Оставьте комментарий

Напишите, что думаете. Нам важно ваше мнение!