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

Как можно расшифровать ключевое слово kwargs в Python?

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

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

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

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

kwargs в Python: расшифровка и практическое использование

kwargs расшифровывается как keyword arguments (именованные аргументы). Это один из самых полезных механизмов Python для написания гибких функций.

Буквальное значение

# kwargs = keyword arguments
def example(**kwargs):
    # kwargs это словарь
    print(type(kwargs))  # <class 'dict'>
    print(kwargs)  # {'name': 'Alice', 'age': 30}

example(name='Alice', age=30)

Как работает двойная звёздочка **

Двойная звёздочка распаковывает именованные аргументы в словарь:

def greet(name, age, city):
    print(f"{name} is {age} years old and lives in {city}")

# Без **kwargs:
greet(name='Alice', age=30, city='NYC')

# С **kwargs:
def flexible_greet(**kwargs):
    greet(**kwargs)

flexible_greet(name='Alice', age=30, city='NYC')

Различие: *args vs **kwargs

def example(*args, **kwargs):
    print("args:", args)      # Кортеж позиционных аргументов
    print("kwargs:", kwargs)  # Словарь именованных аргументов

example(1, 2, 3, name='Alice', age=30)
# args: (1, 2, 3)
# kwargs: {'name': 'Alice', 'age': 30}

Практические примеры

1. Декоратор с гибкостью параметров:

from functools import wraps

def log_call(func):
    @wraps(func)
    def wrapper(*args, **kwargs):
        print(f"Calling {func.__name__}")
        print(f"  args: {args}")
        print(f"  kwargs: {kwargs}")
        result = func(*args, **kwargs)
        print(f"  result: {result}")
        return result
    return wrapper

@log_call
def add(a, b, operation='sum'):
    if operation == 'sum':
        return a + b
    return a * b

add(5, 3)  # С дефолтом
add(5, 3, operation='multiply')  # С кастомным

2. Django: передача параметров в шаблон:

from django.shortcuts import render

def article_view(request, article_id):
    article = Article.objects.get(id=article_id)
    
    context = {
        'article': article,
        'related': article.get_related(),
        'comments': article.comments.all(),
    }
    
    return render(request, 'article.html', context)

# Альтернатива с kwargs:
def flexible_render(request, template_name, **context):
    return render(request, template_name, context)

flexible_render(request, 'article.html', article=article, comments=comments)

3. Конфигурирование объектов:

class DatabaseConnection:
    def __init__(self, **config):
        self.host = config.get('host', 'localhost')
        self.port = config.get('port', 5432)
        self.database = config.get('database', 'app')
        self.user = config.get('user', 'postgres')
        self.password = config.get('password', '')
    
    def connect(self):
        print(f"Connecting to {self.user}@{self.host}:{self.port}/{self.database}")

# Гибкое использование:
db1 = DatabaseConnection()  # Все дефолты
db2 = DatabaseConnection(host='prod.db.com', port=3306, database='main')
db3 = DatabaseConnection(host='staging.db.com')

4. Паттерн: Передача параметров вниз по цепочке:

class APIClient:
    def __init__(self, base_url, **kwargs):
        self.base_url = base_url
        self.timeout = kwargs.get('timeout', 30)
        self.retry = kwargs.get('retry', 3)
        self.auth_token = kwargs.get('auth_token')
    
    def _make_request(self, method, endpoint, **request_kwargs):
        url = f"{self.base_url}/{endpoint}"
        return requests.request(
            method,
            url,
            timeout=self.timeout,
            **request_kwargs
        )
    
    def get(self, endpoint, **kwargs):
        return self._make_request('GET', endpoint, **kwargs)
    
    def post(self, endpoint, **kwargs):
        return self._make_request('POST', endpoint, **kwargs)

# Использование:
client = APIClient('https://api.example.com', auth_token='secret')
response = client.get('/users', params={'page': 1})
response = client.post('/users', json={'name': 'Alice'})

Важный момент: как работает распаковка

def show_info(name, age, city=None):
    print(f"{name}, {age}, {city}")

data = {'name': 'Alice', 'age': 30, 'city': 'NYC'}
show_info(**data)  # Распаковываем словарь
show_info(name='Alice', age=30, city='NYC')  # То же самое

Распространённые ошибки

1. Забыть распаковать:

config = {'host': 'db.com', 'port': 5432}
connection = DatabaseConnection(config)  # Ошибка!
# Правильно: DatabaseConnection(**config)

2. Неправильная последовательность:

# Правильно
def correct(a, b=10, *args, c=20, **kwargs):
    pass

correct(1, 2, 3, 4, c=5, name='Alice')

3. Неправильный доступ:

def process(**kwargs):
    # Правильно:
    name = kwargs.get('name', 'Unknown')
    # Не так:
    # name = kwargs['name']  # KeyError

Практический пример: Flask декоратор

from flask import Flask, request
from functools import wraps

app = Flask(__name__)

def require_auth(**decorators_config):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            token = request.headers.get('Authorization')
            if not token:
                return {'error': 'No auth'}, 401
            
            required_role = decorators_config.get('role', 'user')
            if not check_role(token, required_role):
                return {'error': 'Forbidden'}, 403
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

@app.route('/admin')
@require_auth(role='admin')
def admin_panel():
    return {'message': 'Admin only'}

@app.route('/profile')
@require_auth(role='user')
def user_profile():
    return {'message': 'User profile'}

Итоговое резюме

  • kwargs = keyword arguments — именованные аргументы в словаре
  • ** распаковывает словарь в именованные аргументы (и наоборот)
  • Используй для гибкости: когда не знаешь все параметры заранее
  • Всегда проверяй наличие через .get(), не через []
  • Документируй ожидаемые ключи в docstring