Function implementation using **kwargs

Hi,
I’m trying to implement a function that takes in 2 kwargs, like so:

sorted_with_kwargs(odd = [1,3,5], even = [2,4,6]) 

and returns a list, lst = [1,2,3,4,5,6]
I was able to do it without kwargs:

dct1 = {'odd': [1,3,5]}
dct2 = {'even': [2,4,6]}

def sorted(a,b):
    lst = []
    for i,j in zip(a.values(), b.values()):
        for k,l in zip(i,j):
            lst.append(k)
            lst.append(l)
    return lst

print(sorted(dct1, dct2))
output: [1,2,3,4,5,6]

I think I could just add to a list and then sort it using sort() method, but I’m curious if there’s a way of doing it without it.
By the way, that’s what I’ve got so far:

def sorted_with_kwargs(**kwargs):
    lst = []
    for i in kwargs.values():
        for j in i:
            lst.append(j)
    return lst

Which returns:
[1,3,5,2,4,6]
Thanks!

Hello, @lkszjakubowski, and welcome to the Python Forum!

With the most recent versions of Python, the dict type is ordered, and you can do this:

def sorted_with_kwargs(**kwargs):
    result = []
    for pair in zip(kwargs['odd'], kwargs['even']):
        result.append(pair[0])
        result.append(pair[1])
    return result
    
print(sorted_with_kwargs(odd = [1,3,5], even = [2,4,6]))

Output:

[1, 2, 3, 4, 5, 6]

This assumes that even and odd are in sorted order.

EDIT (November 12, 2021):

See:

Thank you!
I’ve got a question though. What if at the stage of implementing the function I didn’t know the names of arguments, or simply misspelled them later, like so:

def sorted_with_kwargs(**kwargs):
    result = []
    for pair in zip(kwargs['odd'], kwargs['even']):
        result.append(pair[0])
        result.append(pair[1])
    return result
    
print(sorted_with_kwargs(od = [1,3,5], even = [2,4,6]))

I would get a KeyError. Is there a workaround for that?
Thanks :slight_smile:

Yes, the following is possible, as per PEP 468 referenced above, if we can be sure that the first argument passed to the function refers to the odd numbers and the second to the even numbers. The names of the arguments don’t matter.

def sorted_with_kwargs(**kwargs):
    result = []
    num_lists = list(kwargs.values())
    for pair in zip(num_lists[0], num_lists[1]):
        result.append(pair[0])
        result.append(pair[1])
    return result

A KeyError is good! If you misspell a keyword argument, that is a bug in
your code. How will you fix it if you don’t know about it? If you have a
bug in your code, there are three things that can happen:

  • your program will silently do the wrong thing, giving you rubbish
    results, but you won’t know they are rubbish;

  • your code will continue for a while, but will eventually raise an
    error, but far away from where the bug is, and you will have the
    devil’s own time trying to work backwards and debug where the error
    occurs;

  • or your program will immediately raise an error, at the point where
    the error first becomes evident, showing you the exact place where the
    error occurs (or as close to it as possible).

You really, really want the third option whenever possible, the second
option only if it is unavoidable, and never the first option.

To quote Chris Smith:

I find it amusing when novice programmers believe their main job is
preventing programs from crashing. … More experienced programmers
realize that correct code is great, code that crashes could use
improvement, but incorrect code that doesn’t crash is a horrible
nightmare.

I agree with this. Though the workaround posted here is possible, it is better to inform the user of the function that a mistake was made, than to compensate for it silently.

Remember that the user here is the programmer who wrote the wrong

keyword argument in their code, not the person who runs the code (unless

they are the same person).

If they are keyword arguments, you cannot be sure what order the
caller will give them in. Both of these should have identical effect:

result = sorted_with_kwargs(even=[2, 4, 6], odd=[1, 3, 5])

result = sorted_with_kwargs(odd=[1, 3, 5], even=[2, 4, 6])

If you are relying on the keyword arguments to be given in a specific
order, you are doing it wrong.

And if you think that the names of the keyword arguments don’t matter,
you especially are doing it wrong! Of course names matter, that’s why we
use named keyword arguments. It is the name that tells us what the
argument refers to, not the position. That’s why we use keywords and
named parameters, not just positional arguments.

That was stated merely in the context of the workaround that was offered in answer to the user’s question regarding whether or not that manner of workaround was possible. Admittedly, I should have made it clear that while such a workaround was possible, it was inadvisable.

So, @lkszjakubowski, to revisit some of what is above, keyword arguments are a mechanism for enabling programmers to attach meaningful names of arguments passed to certain functions, and to allow them to be specified in any desired order. If such a function has many optional parameters, the programmer who uses the function can decide which ones to specify with a value, and which ones to omit. In an actual program that uses keyword arguments with standardized names, we should not be tolerant of misspellings of the names of those arguments. Instead, an exception should be raised when a name is misspelled.

Again, welcome to the Python Forum. We look forward to seeing more of your questions and replies in the future.

Thank you @Quercus, and @steven.daprano, both of you were very helpful, I appreciate your feedback a lot! It looks, that I didn’t understand the concept of keyword arguments, now everything’s clearer.
I’ll be back :wink:

1 Like

One more issue that still needs attention is this …

That is actually irrelevant to this solution, since the programmer using the function should be free to specify the arguments in either order. The names given with the arguments denote their roles as series of odd and even numbers.

See the content of the referenced PEP 468 for discussion of situations where preservation of the order may matter.