← Назад к вопросам
Когда нужно использовать параметр функции?
1.0 Junior🔥 191 комментариев
#Python Core
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда использовать параметры функции
Параметры функции — это способ сделать функцию гибкой, переиспользуемой и тестируемой. Правильное использование параметров критично для качественного кода.
Основной принцип
Используй параметр ВСЕГДА когда значение может быть разным для разных вызовов функции. Не хардкодь значения — делай их параметрами.
1. Обязательные параметры
Используй когда значение всегда нужно для работы функции:
# Правильно — параметр обязателен
def calculate_discount(price: float, discount_percent: float) -> float:
return price * (1 - discount_percent / 100)
calculate_discount(100, 10) # 90.0
# Неправильно — хардкод
def calculate_discount_bad(price: float) -> float:
discount_percent = 10 # Нельзя менять!
return price * (1 - discount_percent / 100)
2. Опциональные параметры
Используй когда значение может быть не обязательным или есть разумное значение по умолчанию:
# Правильно — значение по умолчанию
def fetch_users(limit: int = 10, offset: int = 0, active: bool = True):
pass
fetch_users() # Использует дефолты
fetch_users(limit=50) # Переопределяет только limit
fetch_users(limit=50, offset=100, active=False)
3. *args (Variadic positional arguments)
Используй когда количество параметров не известно заранее:
# Правильно — неограниченное количество значений
def sum_numbers(*numbers: float) -> float:
return sum(numbers)
sum_numbers(1, 2, 3) # 6
sum_numbers(1, 2, 3, 4, 5) # 15
# Правильно — список или кортеж
def print_all(*messages: str):
for msg in messages:
print(msg)
print_all("Hello", "World", "Python")
4. **kwargs (Variadic keyword arguments)
Используй когда атрибуты объекта динамичны или много опциональных параметров:
# Правильно — конфигурация с динамичными ключами
def create_database(host: str, port: int, **options):
config = {"host": host, "port": port, **options}
return Database(config)
db = create_database(
host="localhost",
port=5432,
user="admin",
password="secret",
ssl=True
)
# Правильно — конструкторы компонентов
def Button(**props):
return f"<button {' '.join(f'{k}={v}' for k, v in props.items())}>"
5. Позиционные и именованные параметры
# Python 3.8+ — можем разделить позиционные и именованные
# / означает все до этого только позиционные
def divide(a: float, b: float, /) -> float:
return a / b
divide(10, 2) # OK
# * означает все после этого только именованные
def create_user(name: str, *, role: str = "user", active: bool = True):
pass
create_user("John", role="admin") # OK
# Комбинирование
def request(method: str, url: str, /, *, headers: dict = None, **kwargs):
pass
6. Типизация параметров
from typing import Optional, Union, Callable
# Явная типизация — всегда лучше
def process(data: list[str]) -> dict[str, int]:
return {item: len(item) for item in data}
# Union — несколько типов
def convert(value: int | str) -> str:
return str(value)
# Optional — может быть None
def fetch(user_id: int, default: Optional[str] = None) -> str:
return default or "Anonymous"
# Callable — функция как параметр
def apply_function(data: list[int], func: Callable[[int], int]) -> list[int]:
return [func(x) for x in data]
apply_function([1, 2, 3], lambda x: x * 2) # [2, 4, 6]
7. Параметры с валидацией
from dataclasses import dataclass
@dataclass
class CreateUserRequest:
username: str
email: str
age: int
def __post_init__(self):
if len(self.username) < 3:
raise ValueError("Username too short")
if self.age < 18:
raise ValueError("Must be 18+")
def create_user(request: CreateUserRequest) -> dict:
return {"username": request.username, "email": request.email}
request = CreateUserRequest("john", "john@example.com", 25)
user = create_user(request)
8. Dependency Injection через параметры
def send_notification(
user_id: int,
message: str,
sender: Callable[[str, str], None] = None
):
if sender is None:
sender = default_email_sender
sender(user_id, message)
# Использование в коде
send_notification(123, "Hello")
# Использование в тестах
test_messages = []
def test_sender(user_id, message):
test_messages.append((user_id, message))
send_notification(123, "Hello", sender=test_sender)
assert (123, "Hello") in test_messages
Ключевые правила
- Все ли переменные должны быть параметрами? Хардкода быть не должно
- Есть ли разумные значения по умолчанию? Добавить дефолты
- Параметры типизированы? Явная типизация всегда
- Слишком ли много параметров? (больше 5) Объединить в объект
- Порядок параметров логичен? Обязательные затем опциональные
Итого
Параметры делают функцию:
- Гибкой — работает с разными данными
- Переиспользуемой — не привязана к конкретным значениям
- Тестируемой — можно передать mock-объекты
- Понятной — явно видно какие данные нужны