← Назад к вопросам

Какие знаешь возможности работы с аргументом в Python?

2.0 Middle🔥 111 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Возможности работы с аргументами в 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)
*argssum(1, 2, 3, 4, 5)
**kwargsКонфиг, опции, параметры
Keyword-onlyОбязательные опции, безопасность
Positional-onlyВнутренние API, публичные методы

Золотое правило

Используй именованные аргументы — они делают код более читаемым и менее подверженным ошибкам. Сделай явным, что какого типа. Потом благодари себя за месяц, когда нужно будет вернуться к коду.