Передать ** kwargs аргумент другой функции с ** kwargs

Я не понимаю следующий пример, скажем, у меня есть следующие функции:

# python likes
def save(filename, data, **kwargs):
    fo = openX(filename, "w", **kwargs) # <- #1
    fo.write(data)
    fo.close()
# python doesnt like
def save2(filename, data, **kwargs):
    fo = openX(filename, "w", kwargs) # <- #2
    fo.write(data)
    fo.close()

def openX(filename, mode, **kwargs):
    #doing something fancy and returning a file object

Почему # 1 - правильное решение, а # 2 - неправильное? **kwargs в основном является dict, поэтому, если я хочу передать аргумент openX, я думаю, что правильный путь был бы без ** и просто давал бы dict. Но python явно не нравится второй и говорит мне, что я дал 3 вместо 2 аргументов. Так в чем причина этого?

Ответ 1

Во втором примере вы предоставляете 3 аргумента: имя файла, режим и словарь (kwargs). Но Python ожидает: 2 формальных аргумента плюс аргументы ключевых слов.

По префиксу словаря "**" вы распаковываете словарь kwargs в аргументы ключевых слов.

Словарь (тип dict) - это единственная переменная, содержащая пары ключ-значение.

"Аргументы ключевого слова" являются параметрами метода key-value.

Любой словарь может быть распакован в аргументы ключевого слова, префикс его с помощью ** во время вызова функции.

Ответ 2

Синтаксис ** указывает Python собирать аргументы ключевых слов в словаре. save2 передает его как аргумент без ключевого слова (объект словаря). openX не видит никаких аргументов ключевого слова, поэтому **args не используется. Вместо этого он получает третий аргумент без ключевого слова (словарь). Чтобы исправить это, измените определение функции openX.

def openX(filename, mode, kwargs):
    pass

Ответ 3

Поскольку словарь является единственным значением. Вам нужно использовать расширение ключевого слова, если вы хотите передать его как группу аргументов ключевого слова.

Ответ 4

За # 2 args будет только формальным параметром с значением dict, но не параметром типа ключевого слова.

Если вы хотите передать параметр типа ключевого слова в аргумент ключевого слова Вам необходимо указать ** перед вашим словарем, что означает ** args

проверьте это для более подробной информации об использовании ** kw

http://www.saltycrane.com/blog/2008/01/how-to-use-args-and-kwargs-in-python/

Ответ 5

Заявление к вышесказанному:

модель def (функции, цель): глобальные аргументы регуляризатор = нет регуляризатор_типа = args.regularizastion_type.lower...

Это часть кода, где мы используем подходы регуляризации L1 и L2, чтобы в конечном итоге уменьшить переоснащение. Я получаю сообщение об ошибке "нет модуля с именем args" после ввода "global args".

Ответ 6

Развернув ответ @gecco, ниже приведен пример, который покажет вам разницу:

def foo(**kwargs):
    for entry in kwargs.items():
        print("Key: {}, value: {}".format(entry[0], entry[1]))

# call using normal keys:
foo(a=1, b=2, c=3)
# call using an unpacked dictionary:
foo(**{"a": 1, "b":2, "c":3})

# call using a dictionary fails because the function will think you are
# giving it a positional argument
foo({"a": 1, "b": 2, "c": 3})
# this yields the same error as any other positional argument
foo(3)
foo("string")

Здесь вы можете увидеть, как работает распаковка словаря, и почему отправка реального словаря не удалась