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

Представьте кофемашину с табличкой total. В щель вы опускаете монету — цену одной чашки. Рядом две ручки: «сколько чашек» и «скидка». Они уже выставлены на count=1 и discount=0, и обычно их никто не трогает.
Хотите три чашки — поворачиваете одну ручку, а скидку оставляете как есть. Без монеты машина не работает. Без поворота ручек работает прекрасно: она берёт то, что на них уже выставлено.
Функции в Python устроены так же. Как вы уже знаете, имена в строке def — это параметры, а значения в вызове — аргументы. Функция total считает стоимость покупки: цену, умноженную на количество, минус скидку. Без настроек каждый вызов передавал бы три числа, даже когда нужна одна чашка без скидки:
def total(price, count=1, discount=0):
return price * count - discount
print(total(250)) # 250
print(total(250, 3)) # 750
print(total(250, 3, 100)) # 650Давайте разберём вызовы по строкам:
total(250)передаёт только цену.countберёт1,discountберёт0, и функция возвращает250.total(250, 3)поворачивает первую ручку:countравен3, скидка по-прежнему0. Результат —750.total(250, 3, 100)задаёт все три параметра и возвращает650.
Аргументы по умолчанию
Запись count=1 в строке def задаёт аргумент по умолчанию: если вызов не передал аргумент для count, параметр получает 1. Это и есть заранее выставленная ручка.
Параметр без такого значения обязателен — это монета. Вызов total() без цены остановится с ошибкой:
TypeError: total() missing 1 required positional argument: 'price'Вы уже встречали аргументы по умолчанию у print. У его параметров sep и end есть значения: пробел и переход на новую строку. Поэтому print без них печатает значения через пробел и заканчивает строку.
В строке def параметры со значением по умолчанию пишут после обязательных. Строка def total(price=0, count): не даёт файлу запуститься: SyntaxError: parameter without a default follows parameter with a default.
Два способа передать аргумент
Аргумент можно передать по месту в списке или по имени параметра. Разберём оба способа.
Позиционные аргументы
Аргументы без имени называют позиционными: они заполняют параметры слева направо. В вызове total(250, 3) число 250 попадает в price, 3 — в count, а discount остаётся равным 0.
Пропустить средний параметр так нельзя. Второй позиционный аргумент всегда попадает во второй параметр. Лишний аргумент тоже не пройдёт: вызов total(250, 3, 100, 5) даёт TypeError: total() takes from 1 to 3 positional arguments but 4 were given.
Именованные аргументы
Чтобы передать скидку и оставить количество по умолчанию, аргумент называют по имени параметра. Это именованный аргумент, как sep="-" в вызове print:
print(total(250, discount=50)) # 200
print(total(discount=50, price=250)) # 200
print(total(250, count=2, discount=100)) # 400Что важно знать об именованных аргументах:
- их порядок не важен: вторая строка даёт то же, что первая;
- позиционные аргументы пишут первыми, именованные — после них;
- один параметр не может получить два значения:
total(250, price=300)даётTypeError: total() got multiple values for argument 'price'; - имя должно совпадать с именем параметра: опечатка в
total(250, cnt=2)даётTypeError: total() got an unexpected keyword argument 'cnt'.
Здесь аналогия с кофемашиной заканчивается. Ручки на машине можно крутить в любом порядке. У позиционных аргументов порядок строгий, и только имя позволяет «дотянуться» до дальней ручки, не трогая ближнюю.
Когда вычисляется значение по умолчанию
Этот вопрос часто задают на собеседовании. Значение по умолчанию вычисляется один раз — когда Python выполняет строку def. Дальше функция хранит готовое значение, а не выражение:
rate = 10
def with_rate(x=rate):
return x
rate = 20
print(with_rate()) # 10
print(with_rate(5)) # 5Разберём по шагам:
- Строка
defвыполняется, когдаrateравна10. Функция запоминает дляxзначение10. rate = 20меняет переменную, но запомненное значение остаётся прежним.with_rate()печатает10, аwith_rate(5)— переданное5.
Частая ошибка
Именованный аргумент поставили перед позиционным:
print(total(price=250, 3)) # ✗SyntaxError: positional argument follows keyword argumentПорядок аргументов проверяется вместе со всем файлом до запуска, поэтому не выполняется ни одна строка. Сначала пишите позиционные аргументы: total(250, 3) или total(250, count=3).
Главное
- Аргумент по умолчанию задают в
defкакcount=1; такие параметры идут после обязательных. - Позиционные аргументы заполняют параметры слева направо, именованные — по имени и в любом порядке.
- В вызове позиционные аргументы стоят перед именованными, иначе файл не запустится.
- Значение по умолчанию вычисляется один раз, когда выполняется строка
def.
Подпишись, чтобы пройти курс
Курс бесплатный. Войди через Telegram и подпишись на канал — откроются все уроки.