Programming, Python

Keyword arguments and merging dictionaries

My next post will probably feature using dictionaries and **kwargs in Python. It’s an interesting subject, and there’s a little change in the way dictionaries can be merged starting in Python 3.9.

You may have seen how you can “eat” function arguments without having to specify them.

For instance, here are three ways to define a function. The first definition requires two arguments, the second requires one or more, and the third will take either zero or as many arguments as you want to pass.

def x(a, b)
def x(a, *args)
def x(*args)

If *args is in the command line, it will consume all non-keyword arguments in the function call. The function sees a tuple called args.

If x were called as x(1, 2, 3) in the second form listed above, a would equal 1 and args would be a tuple, (2, 3).

But what if we defined x like this:

def x(a, b=99, *args)

Icky. Legal, but icky. If you called that as x(1), variable a would equal 1, variable b would equal 99, and args would be empty.

Call it as x(1, 2), and you get a == 1, b ==2, and args empty.

If you call it as x(1,2,3), you don’t get a == 1, b == 99, and args == (2,3), because everything up to *args is considered a non-keyword parameter.

x(1,2,3) will get you a ==1, b == 2, and args would be a tuple with a single member, 3.

I confess, I might use that construct, but I would curse the mirror every morning until I cleaned it up.

Anyway, that’s catching non-keyword arguments with *args. The other side of the coin works, too, passing arguments as *args.

Note that the name “args” is traditional, but not necessary. *anything will work fine for a variable list of arguments not named by the caller.