Глава 13 · Автоматизация с помощью функций
Нет аргументов? Слишком много аргументов!
Значения по умолчанию делают аргумент необязательным — но изменяемое значение по умолчанию скрывает одну из самых известных ловушек Python.
Нет аргументов? Что делать!
Если вызвать функцию без обязательного аргумента, Python сообщит об ошибке. Чтобы аргумент можно было пропустить, ему задают значение по умолчанию:
znachenie_po_umolchaniyu.py
def privetstvie(imya="друг"):
print(f"Привет, {imya}!")
privetstvie() # Привет, друг!
privetstvie("Ада") # Привет, Ада!
| Сигнатура | Роль |
|---|---|
imya | обязательный параметр — если бы не было умолчания |
imya="друг" | необязательный параметр со значением по умолчанию |
Ловушка изменяемого значения по умолчанию
Это один из самых известных сюрпризов Python — и его нужно разобрать не торопясь.
mutable_default_trap.py
def add_task(task, tasks=[]):
tasks.append(task)
return tasks
print(add_task("A"))
print(add_task("B"))
['A']
['A', 'B']
Список по умолчанию создаётся ОДИН РАЗ — когда выполняется def
tasks=[] вычисляется в момент определения функции, а не заново при каждом вызове. Получается один и тот же список-объект по умолчанию, общий для всех вызовов, где аргумент не передан явно.Правильный паттерн: None как отметка «не передано»
mutable_default_fix.py
def add_task(task, tasks=None):
if tasks is None:
tasks = []
tasks.append(task)
return tasks
None — безопасный сигнальный аргумент по умолчанию
None — неизменяемый одиночный объект, поэтому его можно безопасно использовать как значение по умолчанию. Проверка if tasks is None (глава 9: is None) создаёт НОВЫЙ пустой список при каждом вызове без аргумента — ровно то поведение, которое интуитивно ожидалось. Это не единственный способ решить проблему, но самый распространённый.Слишком много аргументов!
Иногда заранее неизвестно, сколько аргументов понадобится передать. Символ
* перед именем параметра собирает любое
количество аргументов в один кортеж (глава 11):
args.py
def summa_vseh(*chisla):
itog = 0
for n in chisla:
itog += n
return itog
print(summa_vseh(1, 2)) # 3
print(summa_vseh(1, 2, 3, 4, 5)) # 15 — сколько угодно аргументов
Именованные аргументы — напоминание
Аргументы можно передавать и по имени, а не только по порядку:
privetstvie(imya="Ада") — подробнее об этом в §13.6.Практика: значения по умолчанию и ловушка изменяемого умолчания
Интерактивный ноутбук прямо в браузере — Python 3.14 через Pyodide, без установки