Хорошо. Итак, я хочу, чтобы вы поняли, а не просто дали ответ, потому что StackOverflow - это объяснение концепции, а не написание кода, давайте разберемся в нескольких моментах:
* args и ** kwargs используются какпроизвольное количество аргументов.
Синтаксис Kwargs ** требует отображения (например, словарь);каждая пара ключ-значение в отображении становится ключевым аргументом.
, в то время как
* args получает кортеж, содержащийпозиционные аргументы.
Теперь давайте рассмотрим простой пример, чтобы понять вашу проблему:
def check(*a,**b):
print(a)
print(b)
Теперь * a требуется кортеж или список или позиционный аргумент, в то время как ** b требует формат dictАргумент keyworded.
Еще один момент, прежде чем приступить к решению проблемы:
* l идиома - распаковать списки аргументов, кортежи, установить
a,*b=(1,2,3,4,5)
print(a)
print(b)
output:
1
[2, 3, 4, 5]
Теперь, если я вызову эту функцию, что-то вроде:
def check(*a,**b):
print("value_a {}".format(a))
print("value_b {}".format(b))
print(check({'y': 5, 'x': 3, 'a': 5,'r':56}))
Теперь * a примет значение, потому что нет аргумента с ключами:
value_a ({'x': 3, 'y': 5, 'a': 5, 'r': 56},)
Но давайте добавим несколько ключевых слов аргумент:
print(check({'y': 5, 'x': 3, 'a': 5,'r':56},key_s=5,values=10))
вывод:
value_a ({'a': 5, 'y': 5, 'r': 56, 'x': 3},)
value_b {'key_s': 5, 'values': 10}
Давайте начнем использовать метод распаковки:
print(check(*{'y': 5, 'x': 3, 'a': 5,'r':56}))
вывод будет:
value_a ('r', 'x', 'y', 'a')
value_b {}
None
Потому что, как я показал, вы * распакуете ключи dict и обработаетони как позиционный аргумент, а не как аргумент keyworded.
Теперь давайте используем ** распаковку, которая будет распаковывать dict как ключ, пары значений:
Я думаю, вы поняли, теперь давайте использовать ** дляотображает dict, поэтому он будет распаковывать dict и каждый ключ, значение будет ключевым аргументом:
print(check(**{'y': 5, 'x': 3, 'a': 5,'r':56}))
вывод:
value_a ()
value_b {'y': 5, 'r': 56, 'a': 5, 'x': 3}
Так что теперь все понятноподумайте.
Теперь вернемся к вашей проблеме:
Как вы сказали, если используете:
def check(a,**b):
print("value_a {}".format(a))
print("value_b {}".format(b))
print(check(**{'y': 5, 'x': 3, 'a': 5,'r':56}))
Вы получаете результат, потому что онберя значение 'a' из dict, а остальные значения берутся ** b
Теперь, если вы хотите использовать * a и ** b, вам необходимо указать:
the positional argument for *a
Keyworded argument for **b
Как вы сказали, что не хотите изменять foo, вы можете попробовать что-то вроде этого:
def bar (*a, **b):
foo((a,),**b)
def foo (*a, **c):
print(c)
print(a)
if __name__ == '__main__':
bar(2,3,4, x=3, y=5)
output:
{'y': 5, 'x': 3}
(((2, 3, 4),),)