User-friendly way to return multiple values from a function in Python

assert foo().bar in foobar().baz

George Shuklin
OpsOps
2 min readNov 27, 2020

--

Personally, I think that dictionary syntax for Python is the least well done thing in Python. All those name[‘in’][‘quotes’][‘and’][‘brakets’] is really hard to read. It’s much better to have names.with.a.dot.notation, isn’t it?

Unfortunately, dot notation is reserved for modules and classes for their moduly and classy things. A dictionary is just not ‘classy’ enough for dot notation. Bummer.

If you want to implement full-fledged class as a return value, you’ll find you need to support all those magic methods on comparison, calling, copying, hashing, etc. It’s a lot of boilerplate code. There are classes to make your life easier (nameddict, etc), but all them is still too much of a hassle for a simple case.

The case I’m talking about is much simpler: just make return more neat and easy to use.

The problem

We need to return a few values from a function.

Naive solutions

The key issue is that return values have zero meaning. To use them one need to unpack values into variables or access them by index:

Indexing from zero adds fun to the count. Is password in an element number 5 or is it in an element number 3?

Another approach is to return a dictionary:

Now we got names for return values. In exchange caller need to suffer:

The good solution

My solution is to use class as a data holder. We’ll ignore all fancy things we can do, and keep code as simple as possible:

The use is a bliss:

But it’s become even better if you consider container types for return values:

In this example we don’t afraid of using class variables with container types, as the class ‘retval’ is created every time function is executed, so, no (un)expected surprises here.

It does not give you the full dot notation, but at least first one is for free:

The reason I usually don’t want to have full dot notation is that those return values may be passed to another function, and that function is going to be surprised with non-standard object (or you need to write a lot of code to not to surprise).

If your adict is not a dictionary, it’s either a surprise, or a lot of code. But one level of ‘classiness’ for multiple return values saves a lot of typing while preserving standard types.

--

--

George Shuklin
OpsOps

I work at Servers.com, most of my stories are about Ansible, Ceph, Python, Openstack and Linux. My hobby is Rust.