Python - unpacking kwargs in local function call

8-Bit Borges picture 8-Bit Borges · Oct 21, 2016 · Viewed 15k times · Source

I would like to pass a dictionary:

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

as a parameter to this 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)

where last.get_track("Radiohead", "Karma Police") is the correct way of calling the local function.

and then call it like this:

lastfm_similar_tracks(items)

I'm getting this error:

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

how should I correct this?

Answer

brianpck picture brianpck · Oct 21, 2016

A few items of confusion:

You are passing the dictionary items as a parameter without the double star. This means that items is treated as the first positional argument, whereas your function only has **kwargs defined.

Here's a simple function:

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

Let's pass it 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

Oops: no positional arguments are allowed. You need to use the double star so that it will print:

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

This leads us to the next issue: kwargs inside the function is a dictionary, so you can't just pass it to last.get_track, which has two positional arguments according to your example. Assuming that order matters (it almost certainly does), you need to get the correct values from the dictionary to be passed:

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