Значения по умолчанию и порядок аргументов
📌 Зачем нужны значения по умолчанию?
Представь ситуацию: ты пишешь функцию для приветствия пользователя. Без значений по умолчанию код выглядел бы так:
def greet(name, greeting):
print(f"{greeting}, {name}!")
greet("Анна", "Привет") # Привет, Анна!
Но что, если в 90% случаев мы хотим использовать стандартное приветствие "Привет"? Здесь на помощь приходят значения по умолчанию:
def greet(name, greeting="Привет"):
print(f"{greeting}, {name}!")
greet("Максим") # Привет, Максим!
greet("Ольга", "Здравствуйте") # Здравствуйте, Ольга!
🔥 Суперсила: теперь функция стала гибкой — работает и со стандартным приветствием, и с кастомным!
⚡ Как правильно задавать значения по умолчанию
1️⃣ Неизменяемые объекты (числа, строки, кортежи) — идеальные кандидаты:
def create_user(email, role="user", is_active=True):
print(f"Создан {role} с почтой {email}. Активен: {is_active}")
2️⃣ Изменяемые объекты (списки, словари) — опасно! Используй None:
# ❌ Плохо (один список на все вызовы!)
def add_task(task, tasks=[]):
tasks.append(task)
return tasks
# ✅ Правильно
def add_task(task, tasks=None):
if tasks is None:
tasks = []
tasks.append(task)
return tasks
🎯 Правило: изменяемые значения по умолчанию — частая причина багов. Всегда используй None для таких случаев!
🔀 Порядок аргументов: строгие правила
Python требует соблюдать четкий порядок параметров:
- Обычные аргументы (без значений по умолчанию)
- Аргументы с дефолтными значениями
- *args (если есть)
- Только ключевые аргументы
- **kwargs (если есть)
# ✅ Правильный порядок
def train_model(data, epochs=10, *, verbose=False, **kwargs):
pass
# ❌ Ошибка!
def bad_func(a=1, b): # SyntaxError
pass
💡 Лайфхак: если порядок сложно запомнить — используй подсказки из IDE (например, PyCharm подсветит ошибку).
🎯 Практика: реальный кейс из веб-разработки
Допустим, мы пишем функцию для API-запроса с типичными параметрами:
def make_api_request(
endpoint,
method="GET",
timeout=5,
retries=3,
headers=None,
):
"""Гибкий HTTP-запрос с настройками по умолчанию."""
if headers is None:
headers = {"User-Agent": "MyApp/1.0"}
print(f"Делаем {method} запрос к {endpoint}")
print(f"Таймаут: {timeout}s, попыток: {retries}")
print(f"Заголовки: {headers}")
# Использование:
make_api_request("/users") # Минимальная конфигурация
make_api_request("/posts", "POST", timeout=10) # Кастомизация
🚀 Фишка: такой подход сочетает удобство для простых случаев и гибкость для сложных.
💡 Продвинутые техники
1. Комбинирование позиционных и именованных аргументов
def connect_db(host, port=5432, user="admin", password=""):
pass
# Можно смешивать стили:
connect_db("localhost", user="danila", password="qwerty")
2. Аннотации типов с дефолтами
def calculate_tax(
income: float,
rate: float = 0.13,
*,
verbose: bool = False
) -> float:
tax = income * rate
if verbose:
print(f"Налог: {tax:.2f}")
return tax
📌 Совет от Данилы Бежина: смотрите его видео про аннотации типов для углубленного изучения.
🧠 Проверь себя
1. Какая ошибка в этом коде?
def process_data(data=[], verbose=True):
pass
2. Напиши функцию send_email, где:
- Обязательный параметр:
to - Необязательные:
subject="Без темы",body="" - Только ключевые:
cc=None,bcc=None
Ответы:
- Опасное изменяемое значение по умолчанию
data=[]. Нужно заменить наNone. - Решение:
def send_email(to, subject="Без темы", body="", *, cc=None, bcc=None):
pass
Теперь ты мастер аргументов Python! 🎓 Пиши чистый и гибкий код с этими приемами.