3

I'm trying to figure out kwargs and do some simple string formatting.

def basic_human(first_name='Jeff', age=42):
    return f"My name is {first_name}, and my age is {age}"


def starwars_fan(movie='A new hope', jedi='Young Obi Wan', **kwargs):
    human_string = basic_human(kwargs)
    return f"{human_string}. My favorite movie is {movie}, and my favorite Jedi is {jedi}."

print(basic_human(first_name='Mr. Baby', age=0.8))
print(starwars_fan(person_name='Chris', jedi='Kit Fisto'))

In the first case, things work fine:

My name is Mr. Baby, and my age is 0.8

In the second case, the person_name parameter comes in as a dict and I'm not sure why:

My name is {'first_name': 'Chris'}, and my age is 42. My favorite movie is A new hope, and my favorite Jedi is Kit Fisto.

Is there a way to make this work without explicitly overriding each of the "basic human" params?

def basic_human(first_name='Jeff', age=42, other_params=None):
    if other_params:
        if 'first_name' in other_params:
            first_name = other_params['first_name']...
    return f"My name is {first_name}, and my age is {age}"
CWiswell
  • 31
  • 4
  • You have to unpack the `kwargs`. It changes it to `human_string = basic_human(**kwargs)`. Also, you pass `person_name='Chris'` which doesn't exist. Did you mean `first_name='Chris'`? – Dock Feb 17 '21 at 23:18
  • Hi, was your question answered? If so, could you please accept and upvote the correct answer? If not, what can be clarified? – Arya McCarthy Mar 19 '21 at 02:09

3 Answers3

1

Change it to this:

human_string = basic_human(**kwargs)

kwargs is a dict containing all of the leftover parameters:

print(kwargs)
# {'first_name': 'Chris'}

The way you wrote it, basic_human's first argument (first_name) is this dict, its second (age) is 42, and other_params is still None.

In other words, your version is equivalent to:

# What you got, not what you want.
basic_human(first_name={'first_name': 'Chris'}, age=42, other_params=None)

What the ** in my version changes is that it expands the dict into arguments. Each key in kwargs becomes a named argument to basic_human, with the corresponding value. (See here for details.)

Arya McCarthy
  • 8,554
  • 4
  • 34
  • 56
1

In order to pass kwargs through the the basic_human function, you need it to also accept **kwargs so any extra parameters are accepted by the call to it.

Secondly, you must pass through kwargs in the same way, i.e. by unpacking them to named arguments when passing them over to basic_human

Like so:

def basic_human(first_name='Jeff', age=42, **kwargs):
    return f"My name is {first_name}, and my age is {age}"


def starwars_fan(movie='A new hope', jedi='Young Obi Wan', **kwargs):
    human_string = basic_human(**kwargs)
    return f"{human_string}. My favorite movie is {movie}, and my favorite Jedi is {jedi}."

print(basic_human(first_name='Mr. Baby', age=0.8))
print(starwars_fan(person_name='Chris', jedi='Kit Fisto'))
Brian Sidebotham
  • 1,706
  • 11
  • 15
0

You have to unpack the kwargs. You have to change it to human_string = basic_human(**kwargs). The ** unpacks the dict. You can also have a dict with the keys first_name and jedi keys and use ** to unpack it.

Also, you pass person_name='Chris' which doesn't exist. Did you mean first_name='Chris'?

Dock
  • 444
  • 5
  • 13