2015-12-09 5 views
2

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

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 нет общих ключей, поэтому нам не нужно беспокоиться о столкновениях param-name).

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

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) 

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

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

ответ

3

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

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

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