Take the 2-minute tour ×
Programmers Stack Exchange is a question and answer site for professional programmers interested in conceptual questions about software development. It's 100% free, no registration required.

Is there any recommended/generally accepted coding style for handling situations where a function returns a tuple of values but only one of those values is used afterwards (note that this is mostly meant for library functions I can't change -- writing a wrapper around the call is probably a bit of overkill…)? Instead of doing

a, b, c = foo()

and then just not using a and b, which of the following variants should be preferred (or is there another one?):

Variant 1 (underscore)

a, _, _ = foo()

(which is very clear and simple but might clash with _ = gettext.gettext used in many applications that use translation)

Variant 2 (dummy name)

a, unused, unused = foo()

(not very appealing, I think, same goes for other names like dummy)

Variant 3 (index)

a = foo()[0]

(to me the ()[0] looks un-pythonic…)

share|improve this question
    
It contrast to my former answer, what happens with variant 3 when you now want to reference 2/3 of the return values? I removed my answer because I realised I didn't know enough about Python to justify it. –  Craige Mar 13 '12 at 18:50
    
@Craige: I did not see your answer before you removed it... Are you asking whether a, b = foo()[0:2] would work? If yes: yes, it does :) –  user49643 Mar 13 '12 at 21:53
    
That was exactly what I was asking. If that works (as you said it does) I'd use variant 3. I'm re-instating my answer given this information. –  Craige Mar 14 '12 at 2:40

5 Answers 5

up vote 6 down vote accepted

Using the underscore for unused variables is definitely acceptable. Be warned though, in some codebases it's not an option as that identifier is reserved as shorthand for gettext. This is the most frequent objection to this style (though it's not an issue for the majority as far as I can judge). I'd still recommend it, and always use it myself.

Names like dummy or unused tend to irritate me personally, and I don't see them terribly often (in Python, that is - I know a Delphi codebase which uses dummy liberally, and it has also leaked into scripts associated with the program in question). I'd advice you against it.

Just extracting one item from the returned tuple is okay too. It also saves some hassle with getting the number of unused values right. Note though that it's has two potential downsides:

  • It doesn't blow up if the number of values is different from what you expect. This may be useful to detect mixups and typos.
  • It only works when the return value is a sequence (that's mostly tuples and lists, but let's stay general). Offhand, I know one class in my code (a 2D vector) that is iterable and yields a constant number of values (and thus can be used in unpacking assignments), but is not indexable.
share|improve this answer
    
I did actually mention gettext in my question :) Anyway, I accepted your answer -- it seems that there is no clear single accepted style but your answer raised some interesting points. –  user49643 Mar 15 '12 at 13:58

Pylint has gotten me in the habit of doing it this way:

widget, _parent, _children = f()

That is, unused results have a descriptive name prefixed by _. Pylint regards locals prefixed with _ as unused, and globals or attributes prefixed with _ as private.

share|improve this answer

If in your entire project, you're only doing this this once or very rarely wrt the particular function, I would use Variant 1 if you know gettext isn't a problem in that module, and otherwise Variant 3.

On the other hand, if you were doing this a lot - and especially if each time you want a different subset of the return values (making a wrapper to just return the ones you care about unviable), it might be beneficial to write a wrapper that puts the results into a named tuple, or an instance of some other descriptive class, which would let you do:

bar = foo()

And then work with bar.a, bar.b and bar.c.

share|improve this answer

I'm a non-Python programmer, but to me the third variant makes the most sense.

In variant 3 you are absolutely clear which values your are interested in dealing with. In variant 1 and 2, you are assigning the values back to variables, and thus, they can be used. You may have named them obscurely, but poor naming isn't really a solution to any problem.

Aside from clarity, why would you want to assign unused values to a slot in memory (as in variants 1 and 2)? This would be a poor solution in terms of memory management.

share|improve this answer

Here's a general rule: If only 1 of the returned values is used, why not simply return that 1 value? In case the flag is being called from multiple places, keep a flag for the same and return values as per the flag.

EDIT:

In case I was in your situation, and I hadn't written the function, I'd perhaps go for Variant 2. I'd keep the dummy names there so that the parameters can be used in case need arises. Slicing a list will have a little overhead. Perhaps you can spare a few bytes to receive the unwanted data.

share|improve this answer
    
-1 I'm guessing he didn't define the function, and thus can't change what it returns. I think he's referring to when the function returns 3 values, but he only cares about 1 in his current use-case. –  Craige Mar 13 '12 at 18:31
    
@Craige: Yes, I meant functions I could not change -- I added a note to my question clarifying that. –  user49643 Mar 13 '12 at 18:33
    
Are you sure about the overhead? I tried a very simple ipython test: %timeit a, _, _ = foo() vs. %timeit a = foo()[0] which resulted in 123ns vs. 109ns, i.e. the slicing seems to be actually faster than the value unpacking. Or did you have any specific situation in mind? –  user49643 Mar 13 '12 at 21:50
2  
Another plausible scenario is that you don't need all the values for some calls. –  Keith Thompson Mar 14 '12 at 0:59

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.