Программирование и IT

Python: функции

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

Обновлено
В этой статье

Объявление и возврат#

Функция начинается со слова def, имени, скобок со списком параметров и
двоеточия. Тело — с отступом в четыре пробела.

def greet(name):
    """Вернуть приветствие для имени."""
    return f"Привет, {name}!"

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

Строка в тройных кавычках сразу под def — документация функции, она доступна
через help(greet) и greet.__doc__. Писать её полезно даже для себя: через
месяц это единственный способ вспомнить, что функция обещает.

Если return не выполнился, функция возвращает None — ничего не «падает»,
просто результат пустой:

def add(a, b):
    print(a + b)        # печатает, но не возвращает

result = add(2, 3)      # 5
print(result)           # None

Эта путаница print и return — ошибка номер один у начинающих. print
показывает значение человеку, return отдаёт его коду.

Аргументы: позиционные, именованные, со значением по умолчанию#

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

print(power(3))              # 9
print(power(3, 3))           # 27
print(power(exp=3, base=2))  # 8

Позиционные аргументы сопоставляются по порядку, именованные — по имени и
могут идти в любом порядке. Параметры со значением по умолчанию объявляются
только после обычных: def f(a=1, b) — синтаксическая ошибка.

Звёздочка в списке параметров делает всё, что за ней, «только по имени» — это
спасает от нечитаемых вызовов вроде save(data, True, False):

def save(data, *, overwrite=False):
    return f"{data} / перезапись: {overwrite}"

print(save("отчёт", overwrite=True))   # отчёт / перезапись: True

Переменное число аргументов#

*args собирает лишние позиционные аргументы в кортеж, **kwargs — именованные
в словарь.

def total(*args, **kwargs):
    print(args, kwargs)
    return sum(args)

print(total(1, 2, 3, скидка=5))
  # (1, 2, 3) {'скидка': 5}
  # 6

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

nums = [2, 3]
print(power(*nums))                      # 8
print(power(**{"base": 5, "exp": 3}))    # 125

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

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

def collect(item, box=[]):
    box.append(item)
    return box

print(collect("a"))   # ['a']
print(collect("b"))   # ['a', 'b']  — не то, чего ждали

Лечится одинаково всегда: умолчанием ставят None, а настоящее значение
создают внутри.

def collect(item, box=None):
    if box is None:
        box = []
    box.append(item)
    return box

print(collect("a"))   # ['a']
print(collect("b"))   # ['b']

Область видимости#

Имя, которому присвоили внутри функции, считается локальным для всей функции —
даже если присваивание стоит в последней строке.

counter = 0

def bump():
    global counter
    counter += 1

bump()
print(counter)      # 1

Без строки global counter тот же код упал бы с UnboundLocalError. Но
global — плохая привычка: чаще нужно принять значение аргументом и вернуть
новое. Читать глобальные значения внутри функции можно и без объявления.

Небольшая практика: напиши функцию stats(*numbers), которая возвращает
кортеж из минимума, максимума и среднего, и проверь, что она работает и от
stats(1, 2, 3), и от stats(*[1, 2, 3]). Дальше пригодятся
декораторы — они как раз надстройки над функциями,
и исключения, чтобы аккуратно сообщать об
ошибочных аргументах.

План по этапам

  1. Простая функция с returnНаписать функцию, которая принимает два числа и возвращает их сумму; вывести результат через print.
  2. Умолчания и именованные аргументыДобавить параметр со значением по умолчанию и вызвать функцию тремя способами.
  3. Собрать *argsФункция с переменным числом аргументов, которая считает среднее; вызвать её с раскрытием списка.
  4. Воспроизвести ловушкуВыполнить пример с box=[] дважды подряд и убедиться, что список накапливает значения.
  5. Переписать безопасноЗаменить умолчание на None и проверить, что вызовы больше не влияют друг на друга.

Начать изучать эту тему у себя

План ляжет в твой репозиторий: отмечай этапы, веди конспект — история изменений покажет, как ты продвинулся.

Начать план

Проверь себя

1.Что выведет: def f(a, b=2): return a * b; print(f(3))?

2.Что напечатает: def f(x): print(x); r = f(1); print(r)?

3.Что выведет второй вызов: def c(i, box=[]): box.append(i); return box; c('a'); print(c('b'))?

4.Что вернёт: def t(*args): return len(args); t(1, 2, 3, 4)?

Источники

Было полезно?

Ещё темы

Программирование и IT Как изучить Python с нуля Python хорош для первого знакомства с программированием: код читается почти как текст, а стандартная библиотека закрывает большинство бытовых задач. Этот план ведёт от установки интерпретатора до собственных скриптов, покрытых тестами, — примерно за четыре месяца при занятиях около часа в день. Программирование и IT Python: декораторы Декоратор — это функция, которая принимает другую функцию и возвращает новую, с добавленным поведением. Знак `@` перед определением — просто короткая запись присваивания. Если держать это в голове, вся тема разбирается за один вечер. Программирование и IT Python: классы Класс описывает, из каких данных состоит объект и что он умеет делать. Конструктор `__init__` заполняет новый объект, `self` — ссылка на него самого. Ниже — минимальный рабочий класс, разница между атрибутом класса и атрибутом экземпляра и способы сделать код короче. Программирование и IT Python: чтение файла Работа с файлом состоит из трёх шагов: открыть, прочитать или записать, закрыть. Закрытие лучше не делать руками — для этого есть оператор `with`. А главный параметр, про который забывают, — кодировка: без неё один и тот же код на разных машинах читает файл по-разному. Программирование и IT Python: задачи с решениями Подборка задач по возрастанию сложности — от разворота строки до генератора и декоратора-счётчика. Сначала решай сам и только потом открывай разбор: сравнение своего кода с чужим даёт больше, чем чтение готового. Все решения проверены на Python 3. Программирование и IT Python: срезы Срез вырезает из последовательности кусок по правилу «с какого индекса, до какого, с каким шагом». Запись компактная, но у неё два места, где почти все ошибаются: правая граница не включается, а при отрицательном шаге границы меняются местами. Разберём оба.

Ещё сценарии