Разделение 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