Python — распаковка kwargs при вызове локальной функции

#python #keyword-argument

#python #ключевое слово-аргумент

Вопрос:

Я хотел бы передать dictionary :

 items = {"artist": "Radiohead", "track": "Karma Police"}
  

в качестве параметра для этого function :

 def lastfm_similar_tracks(**kwargs):

    result = last.get_track(kwargs)
    st = dict(str(item[0]).split(" - ") for item in result.get_similar())
    print (st)
  

где last.get_track("Radiohead", "Karma Police") — правильный способ вызова локальной function .

а затем вызовите это следующим образом:

 lastfm_similar_tracks(items)
  

Я получаю эту ошибку:

TypeError: lastfm_similar_tracks() takes exactly 0 arguments (1 given)

как я должен это исправить?

Ответ №1:

Несколько элементов путаницы:

Вы передаете словарь items в качестве параметра без двойной звездочки. Это означает, что items рассматривается как первый позиционный аргумент, тогда как ваша функция только **kwargs определила.

Вот простая функция:

 >>> def f(**kwargs):
...     print (kwargs)
  

Давайте передадим это items :

 >>> items = {"artist": "Radiohead", "track": "Karma Police"}
>>> f(items)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: f() takes 0 positional arguments but 1 was given
  

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

 >>> f(**items)
{'artist': 'Radiohead', 'track': 'Karma Police'}
  

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

 result = last.get_track(kwargs['artist'], kwargs['track'])
  

Ответ №2:

Первая проблема: вам нужно передать items вот так:

 lastfm_similar_tracks(**items)
  

Вторая проблема, внутренняя lastfm_similar_tracks , kwargs — это словарь, в котором ключи не имеют определенного порядка, поэтому вы не можете гарантировать порядок при передаче в get_track . Лучшее, что вы можете сделать, это:

 result = last.get_track(kwargs['artist'], kwargs['track'])
  

На этом этапе код должен работать так, как вы задумали. Однако я сомневаюсь в использовании **kwargs in lastfm_similar_tracks : вам действительно нужно определять это таким образом? Как насчет:

 def lastfm_similar_tracks(artist, track, **kwargs):
    result = last.get_track(artist, track)
    # The rest of your code here
  

Тогда вы можете назвать это следующим образом:

 lastfm_similar_tracks(**items)
  

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

Ответ №3:

По сути, ** kwargs в определении функции означает, что именованные аргументы не должны распаковываться в переменные.

Чтобы вызвать некоторую функцию со словарем аргументов, они все равно должны быть представлены в виде именованных параметров. Иначе python «считает» предоставленный аргумент позиционным

Таким образом, вы должны вызывать свою функцию как:

 items = {"artist": "Radiohead", "track": "Karma Police"}
lastfm_similar_tracks(**items)
  

Комментарии:

1. Обратите внимание, что это все равно вызовет ошибку, потому что он передает kwargs словарь в last.get_track

2. @agg3l Я пробовал это. это дает мне TypeError: get_track() takes exactly 3 arguments (2 given)

3. @brianpck Хороший момент, я пропустил эту ошибку в блоке примера кода