Какие знаешь возможности работы с аргументом в Python?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Возможности работы с аргументами в Python
Это один из ключевых аспектов функционального программирования на Python. За 10+ лет я использовал все способы, и каждый имеет свою нишу.
1. Позиционные аргументы (Positional Arguments)
Самый базовый способ:
def greet(name, age):
return f"{name} имеет возраст {age}"
print(greet("Иван", 30)) # Работает
print(greet(30, "Иван")) # Неправильно, но синтаксически валидно
Проблема: Легко перепутать порядок. Решение: Используй именованные аргументы.
2. Именованные аргументы (Keyword Arguments)
Это моя рекомендация для production кода:
def create_user(name, email, age=25, is_active=True):
return {"name": name, "email": email, "age": age, "is_active": is_active}
# ✅ ЛУЧШЕ: ясно, что какие значение
user = create_user(name="Иван", email="ivan@example.com", age=30)
# Можно переордировать
user = create_user(email="ivan@example.com", name="Иван", age=30)
# Можно смешивать позиционные и именованные
user = create_user("Иван", email="ivan@example.com")
3. Аргументы с дефолтными значениями
Одна из самых полезных возможностей:
def connect_db(host="localhost", port=5432, timeout=30):
return f"Подключаюсь к {host}:{port} с timeout={timeout}"
print(connect_db()) # localhost:5432 timeout=30
print(connect_db(host="remote.server")) # remote.server:5432 timeout=30
print(connect_db(port=3306, timeout=60)) # localhost:3306 timeout=60
Важное правило: Аргументы с дефолтами должны идти ПОСЛЕ обязательных:
# ❌ ОШИБКА
def bad_func(age=25, name):
pass
# ✅ ПРАВИЛЬНО
def good_func(name, age=25):
pass
4. *args — переменное число позиционных аргументов
Когда не знаешь, сколько аргументов придёт:
def sum_numbers(*numbers):
"""numbers будет кортежем"""
return sum(numbers)
print(sum_numbers(1, 2, 3)) # 6
print(sum_numbers(1, 2, 3, 4, 5, 6)) # 21
print(sum_numbers()) # 0
# Распаковка
values = [1, 2, 3, 4, 5]
print(sum_numbers(*values)) # 15
Частый случай:
def log_message(level, *args):
"""Логирование с переменным количеством строк"""
message = " ".join(str(arg) for arg in args)
print(f"[{level}] {message}")
log_message("INFO", "Ошибка в", "файле", "config.py") # [INFO] Ошибка в файле config.py
5. **kwargs — переменное число именованных аргументов
Для передачи неизвестного набора опций:
def create_element(tag, **attributes):
"""attributes будет словарём"""
attrs = " ".join(f'{k}="{v}"' for k, v in attributes.items())
return f"<{tag} {attrs}>"
print(create_element("div", id="main", class_="container", data_user="123"))
# <div id="main" class_="container" data_user="123">
Практический пример:
def configure_service(**config):
"""Гибкая конфигурация"""
defaults = {"timeout": 30, "retries": 3, "debug": False}
defaults.update(config) # Переопределяем только нужные параметры
return defaults
config = configure_service(timeout=60, debug=True)
print(config) # {'timeout': 60, 'retries': 3, 'debug': True}
6. Комбинирование *args и **kwargs
Мощная комбинация для максимальной гибкости:
def flexible_func(first, *args, debug=False, **kwargs):
print(f"first: {first}")
print(f"args: {args}")
print(f"debug: {debug}")
print(f"kwargs: {kwargs}")
flexible_func(1, 2, 3, 4, debug=True, name="test", value=42)
# first: 1
# args: (2, 3, 4)
# debug: True
# kwargs: {'name': 'test', 'value': 42}
Важно: Порядок должен быть: позиционные → *args → именованные (с дефолтами) → **kwargs
# ✅ ПРАВИЛЬНЫЙ ПОРЯДОК
def correct(a, b, *args, debug=False, timeout=30, **kwargs):
pass
# ❌ НЕПРАВИЛЬНЫЙ ПОРЯДОК
def wrong(*args, a, b, **kwargs): # SyntaxError
pass
7. Распаковка аргументов при вызове
Можно распаковывать списки и словари:
def multiply(a, b, c):
return a * b * c
# Распаковка списка
numbers = [2, 3, 4]
print(multiply(*numbers)) # 24
# Распаковка словаря
params = {"a": 2, "b": 3, "c": 4}
print(multiply(**params)) # 24
8. Positional-only параметры (Python 3.8+)
Параметры, которые НЕЛЬЗЯ передавать как именованные:
def pow_func(base, exponent, /, modulo=None):
"""base и exponent можно передавать только позиционально"""
result = base ** exponent
if modulo:
result %= modulo
return result
print(pow_func(2, 3)) # ✅ 8
print(pow_func(base=2, exponent=3)) # ❌ TypeError
Применение: Защита от случайного изменения поведения, когда аргумент случайно становится именованным.
9. Keyword-only параметры (после *)
Параметры, которые МОЖНО передавать ТОЛЬКО как именованные:
def send_email(to, subject, *, body, cc=None, bcc=None):
"""body обязателен как именованный параметр"""
return f"Email to {to}: {subject}"
# ✅ ПРАВИЛЬНО
send_email("user@example.com", "Hello", body="Message")
# ❌ НЕПРАВИЛЬНО
send_email("user@example.com", "Hello", "Message") # TypeError
10. Декораторы для работы с аргументами
Декораторы могут модифицировать аргументы:
from functools import wraps
def validate_positive(*param_names):
"""Валидирует, что указанные параметры > 0"""
def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
for param in param_names:
if param in kwargs and kwargs[param] <= 0:
raise ValueError(f"{param} должен быть > 0")
return func(*args, **kwargs)
return wrapper
return decorator
@validate_positive("age", "salary")
def create_employee(name, age, salary):
return {"name": name, "age": age, "salary": salary}
print(create_employee("Иван", age=30, salary=50000)) # ✅ OK
# create_employee("Иван", age=-5, salary=50000) # ❌ ValueError
11. Практический пример: гибкий запрос в БД
def query_users(*ids, status="active", limit=10, **filters):
"""Гибкий запрос с множественными фильтрами"""
where_clauses = []
params = []
if ids:
where_clauses.append(f"id IN ({','.join('?' * len(ids))})")
params.extend(ids)
if status:
where_clauses.append("status = ?")
params.append(status)
# Фильтры из **kwargs
for key, value in filters.items():
where_clauses.append(f"{key} = ?")
params.append(value)
where = " AND ".join(where_clauses) if where_clauses else "1=1"
sql = f"SELECT * FROM users WHERE {where} LIMIT {limit}"
return sql, params
print(query_users(1, 2, 3, status="active", age=25, city="Moscow"))
# ('SELECT * FROM users WHERE id IN (?,?,?) AND status = ? AND age = ? AND city = ? LIMIT 10',
# [1, 2, 3, 'active', 25, 'Moscow'])
Чеклист выбора типа аргумента
| Когда использовать | Пример |
|---|---|
| Позиционные | len(list), print("Hello") |
| Именованные | pd.read_csv("file.csv", sep=",") |
| Дефолты | sleep(seconds, background=False) |
| *args | sum(1, 2, 3, 4, 5) |
| **kwargs | Конфиг, опции, параметры |
| Keyword-only | Обязательные опции, безопасность |
| Positional-only | Внутренние API, публичные методы |
Золотое правило
Используй именованные аргументы — они делают код более читаемым и менее подверженным ошибкам. Сделай явным, что какого типа. Потом благодари себя за месяц, когда нужно будет вернуться к коду.