I've often been frustrated by the lack of flexibility in Python's iterable unpacking.
Take the following example:
a, b = range(2)
Works fine. a
contains 0
and b
contains 1
, just as expected. Now let's try this:
a, b = range(1)
Now, we get a ValueError
:
ValueError: not enough values to unpack (expected 2, got 1)
Not ideal, when the desired result was 0
in a
, and None
in b
.
There are a number of hacks to get around this. The most elegant I've seen is this:
a, *b = function_with_variable_number_of_return_values()
b = b[0] if b else None
Not pretty, and could be confusing to Python newcomers.
So what's the most Pythonic way to do this? Store the return value in a variable and use an if block? The *varname
hack? Something else?
As mentioned in the comments, the best way to do this is to simply have your function return a constant number of values and if your use case is actually more complicated (like argument parsing), use a library for it.
However, your question explicitly asked for a Pythonic way of handling functions that return a variable number of arguments and I believe it can be cleanly accomplished with decorators. They're not super common and most people tend to use them more than create them so here's a down-to-earth tutorial on creating decorators to learn more about them.
Below is a decorated function that does what you're looking for. The function returns an iterator with a variable number of arguments and it is padded up to a certain length to better accommodate iterator unpacking.
Which outputs what you're looking for:
The decorator basically takes the decorated function and returns its output along with enough extra values to fill in
max_values
. The caller can then assume that the function always returns exactlymax_values
number of arguments and can use fancy unpacking like normal.Here's an alternative version of the decorator solution by @supersam654, using iterators rather than lists for efficiency:
It's used in the same way:
This could also be used with non-user-defined functions like so: