почему ** не распаковывает kwargs при вызове функции?

Вот что меня некоторое время беспокоило:

def test (*args, **kwargs):
    print target

test(foo='bar', target='baz')

Я бы предположил, что target='test'в вызове aFunc внизу закончится в kwargs (и это так), и я также предположил бы, что ** будет распаковывать kwargs в вызове функции, поэтому target будет существовать как аргумент ключевого слова внутри aFunc. Это не так. Я знаю, что он приходит как словарь, но мне нужно, чтобы этот словарь распаковывался в списке аргументов. Это возможно? Короче говоря, есть ли способ, чтобы *args и **kwargs исчезли, а настоящие args и kwargs вошли в вызов?

Редактировать: Я собрал случай, когда может помочь распаковка *args и **kwargs:

Скажем, у меня есть функция, которая печатает список:

def printList (inputList=None):
    print inputList

Я хочу, чтобы list и получить список по умолчанию:

def ensureList (listFunc):
    def wrapper (inputList=None):
        listFunc(inputList=inputList or ['a','default','list'])
    return wrapper

@ensureList
def printList (inputList=None):
    print inputList

Теперь я хочу немного усложнить повторитель списка:

@ensureList
def repeatList (inputList=None):
    print inputList*2

Это прекрасно работает. Но теперь я хочу, чтобы переменная повторялась:

@ensureList
def repeatList (times, inputList=None):
    print inputList*times

Теперь вы могли бы сказать:

repeatList(5)

Будет сгенерирован список по умолчанию и повторен 5 раз.

Конечно, это не удается, потому что оболочка не может обрабатывать аргумент времени. Я мог бы, конечно, сделать это:

@ensureList
def repeatList (inputList=None, times=1)

Но тогда мне всегда придется делать это:

repeatList(times=5)

И, возможно, в некоторых случаях я хочу принудительно предоставить значение, поэтому arg без ключевого слова имеет смысл.

Когда я впервые столкнулся с подобными проблемами в прошлом году, я подумал, что простым решением будет удаление требований из оболочки:

def ensureList (listFunc):
    "info here re: operating on/requiring an inputList keyword arg"
    def wrapper (*args, **kwargs):
        listFunc(inputList=inputList or ['a','default','list'])
    return wrapper

Однако это не работает. Вот почему я хотел бы, чтобы args и kwargs действительно расширялись, или я хотел бы иметь способ сделать расширение. Тогда какие бы аргументы и kwargs я ни предоставлял, они фактически заполняют аргументы, а не список и дикт. Документация в обертке объясняет требования. Если вы передадите inputList, он действительно войдет, и inputList в обратном вызове RepeatList из оболочки будет действительным. Если бы вы не передали inputList, он создал бы его при обратном вызове RepeatList со списком по умолчанию. Если бы вашей функции было все равно, но она использовала *kwargs, она просто изящно приняла бы это без проблем.

Приносим извинения, если что-то из вышеперечисленного неверно (выходит за рамки общей концепции). Я напечатал его здесь, непроверенный, и уже очень поздно.

6
задан Gary Fixler 23 May 2012 в 11:40
поделиться