Разделение kwargs между вызовами функций

Время от времени я сталкиваюсь с этой дилеммой. Предположим, у меня есть такая функция:

def foo(..., **kwargs):
    ...
    actor = make_actor(..., **a_kwargs)
    return actor.act(..., **b_kwargs)

Я хочу, чтобы вызывающая сторона указала kwargs для передачи make_actor() (a_kwargs) и act() (b_kwargs). Проблема, конечно, в том, что foo можно только взять **kwargs один раз.

(Почти во всех случаях a_kwargs и b_kwargs не имеют общих ключей, поэтому нам не нужно беспокоиться о конфликтах имен-параметров).

Я могу придумать несколько подходов, каждый из которых имеет свои явные недостатки / ограничения.

def foo1(..., **kwargs):
    ...
    a_kwargs = {k:kwargs.pop(k) for k in kwargs.keys() if k in ['arg1','arg2',...]}
    actor = make_actor(..., **a_kwargs)
    return actor.act(..., **kwargs)

def foo2(..., arg1=DEFAULT1, arg2=DEFAULT2, ..., **b_kwargs):
    ...
    actor = make_actor(..., arg1=arg1, arg2=arg2, ...)
    return actor.act(..., **b_kwargs)

def foo3(..., a_kwargs={}, **b_kwargs):
    ...
    actor = make_actor(..., **a_kwargs)
    return actor.act(..., **b_kwargs)

def foo4(..., a_kwargs={}, b_kwargs={}):
    ...
    actor = make_actor(..., **a_kwargs)
    return actor.act(..., **b_kwargs)

Какой самый питонический? Есть ли другой подход, который я упустил, который превосходит четыре выше?

В общем случае мы можем разделить kwargs для передачи более чем двум другим функциям.

1 ответ

Решение

В общем, четвертый вариант имеет смысл.

Даже если это ставит под угрозу возможность использования kwargs в вашей основной функции это делает код понятным, учитывает будущие изменения и уменьшает чрезмерный список аргументов. Это также не означает, что у вас есть чрезмерный список kwargs и словарь, входящий в ту же функцию, что кажется противоречивым.

Simple is better than complex, Readability counts, practicality beats purity

Другие вопросы по тегам