Are multiple return values really harmful? (Re: determining the number of output arguments)

Dave Brueck dave at pythonapocrypha.com
Thu Nov 18 09:40:39 EST 2004


Jeremy Bowers wrote:
> You take every example mentioned to date, which is largely:
> 
> * OS code trying to be as thin as possible (stat, socket)
> * math-type code where the tuple really is the class, as you suggest
> * more-or-less contrived one- or two-liner code
> 
> and you've still got way, way, way less than 1% of the code of the vast
> majority of programs. 
> 
> Like any other code smell, there are times to use it. But I say it's a
> *smell*, and those of you implicitly reading that to mean "Returning
> tuples is *never* a good idea" are doing me a disservice; please go look
> up "code smell" and the word "generally". 

Well, the first page I found that listed the term "code smell" also mentioned 
"code wants to be simple", and having scanned through a good sized chunk of 
Python code looking to see where multiple return values were used, I am now of 
the opinion that, not only are multiple return values _not_ automatically code 
smell, but they are one of the key ingredients to avoiding monolithic functions 
(and thus they help keep code simple).

The code I looked through had about 4500 return statements. Of those, roughly 
350 were returns with multiple values. Of those, 26 had 4 or more return values 
- if code smell is a hint that something _might_ be wrong, I'd say those 26 have 
code smell, but the remaining 320 or so do not automatically raise concern (I 
inspected those 26 in detail and saw only 4 or 5 cases that'd be removed next 
time the code got refactored).

> If you use it every once in a while where it is the right solution, great.
> I do too. If you're using it every other function in a module, and it
> isn't a thin wrapper around some other library, you've got a code smell.

I found that multiple return values were not often used in "public" functions 
(those meant to be accessible from outside the module). Instead the most common 
use case was between functions that had been separated to divide the problem 
into smaller, testable code chunks (i.e. - rather than having a huge function to 
parse a log line, perform computations, and send the results to output, there 
was a function that'd take the raw data, call a helper function to parse it, 
call another helper to compute the result, and call another to send the results 
off for output)

Without the ability to return multiple values, it would be much more cumbersome 
to split the code into small, easily understood chunks because for any 
non-trivial task, each logical "step" in that task often has multiple inputs as 
well as multiple outputs.

After reviewing the code, I think that the use of multiple return values is, in 
and of itself, _almost never_ a good hint of a problem - way too many false 
positives (a better rule of thumb would be that code that returns BIG tuples has 
code small).

> (It's probably a class or two trying to get out.)

No, at least not in the code I looked at - in the vast majority of the uses of 
multiple return values, the coupling between the functions was already very 
tight (specialized) and the callee-caller relationship was one-to-one or 
one-to-few (the function returning multiple values was called by one or very few 
functions), and the data didn't move around between function as a unit or group, 
such that making a class would have been pure overhead like many C structures - 
never reused, and used only to cross the "bridge" between the two functions 
(immediately unpacked and discarded upon reception).

> You've got a *big* code
> smell if you are unpacking those return values many times, because now
> you've hard coded the size of the tuple into the code in many places. 

Yes, this was mentioned previously.

-Dave



More information about the Python-list mailing list