10

Is it okay/good practice to return different number of return values from a function in Python? If yes, how should the caller handle the return values? e.g.

def func():
    if(condition_1):
        return 1,2
    if(condition_2):
        return 1
    if(condition_3):
        return 1,2,3,4

Note: condition_1,condition_2 and condition_3 are local to the function func so the caller has no idea how many values will be returned.

Suresh Kumar
  • 11,241
  • 9
  • 44
  • 54
  • 5
    best is to return a list with values. It is good to have consistency in program. – shivams Jun 08 '15 at 07:26
  • You can use tuples as well. – Vikas Ojha Jun 08 '15 at 07:27
  • 4
    You are only returning one object in each case, two of them are tuples. Personally I would always return the same type of object, even in the single value case, for consistency, but that's subjective. – cdarke Jun 08 '15 at 07:31
  • 1
    Although duplicate offer is quite similar, there are some important key differences, like different number of returned values. So it is not a duplicate. – Mp0int Jun 09 '15 at 06:44

4 Answers4

9

Is it pythonic for a function to return multiple values? have a great explanation in this.

But in your case, it depends on your use-case. If you know how to handle returning data, then there is no problem in using this. Like:

def func():
    if(condition_1):
        return a,b
    if(condition_2):
        return (a, )
    if(condition_3):
        return c,d,e,f
    if(condition_4):
        return a,b

vals = func()
if len(vals) == 2:
    # We are sure that we will get `a,b` in return
    do something ...
elif len(vals) == 3:
    ...

In example above, function that will process vals tuple knows how to handle returning data according to some criteria. It have 2 return possibilities that returns the same data!

If you know exactly how to handle data, then it is ok to go with different number of returns. The key point in here is functions do a single job. If your have problems in recognizing the return values, then your function is doing more than one job or you must avoid using different number of arguments.

kett
  • 877
  • 3
  • 9
  • 22
Mp0int
  • 18,172
  • 15
  • 83
  • 114
6

It's okay to return multiple values, but you must keep all your returns in same form/type for using:

def func():
    if(condition_1):
        return 1, 2
    if(condition_2):
        return 1,    # return a tuple same as the others
    if(condition_3):
        return 1, 2, 3, 4
Sinux
  • 1,728
  • 3
  • 15
  • 28
6

I would avoid this. In general (although there are occasionally exceptions), as other people have mentioned, it is a good idea to return the same type of object from each branch of a function. However, this goes deeper than just wrapping singular return values in one-element tuples - consider a pattern whereby you return the same number of things (in the same order), and using None or some type-specific 'null' value (the Null Object Pattern) for any that don't apply to that branch.

This means client code can always do this:

a, b, c, d, e = func()

and ignore any values it doesn't care about. With the null object pattern also in the mix, then even code that cares about the potentially non-existent values might not have to special case them. If you vary the length of the tuple, every call has to be prepared for the results of any branch, which means it nearly has to match your branches.

A really nice way, for you and for calling code, to enforce this kind of pattern is to use collections.namedtuple. This also has the nice benefit of making your code immediately more self-documenting.

lvc
  • 34,233
  • 10
  • 73
  • 98
2

While this is subjective, I like to return dictionaries - it helps to avoid caring for the order of what is returned, I can have a partial return (3 elements out of 5 for instance) and it makes the code more readable.

def func():
    if(condition_1):
        return {'name': 'Joe', 'age': 32}
    if(condition_2):
        return {'name': 'Mary'}

res = func()
name = res.get('name', 'unknown')
age = res.get('age', 0)
WoJ
  • 27,165
  • 48
  • 180
  • 345
  • Tuples are ordered too. Alse they can be sliced like lists too. The difference is only in mutability. Lists can be changed when tuples are immutable. – Ihor Pomaranskyy Jun 08 '15 at 07:42
  • @IgorPomaranskiy: it is less the order itself which is important for me, rather the fact that I return `{'age': 32, 'name': 'Joe'}` instead of `32, 'Joe'`. In the first case I know I must `.get()` a value, in the other one I usually need to check in which order I returned the data. – WoJ Jun 08 '15 at 07:51
  • 1
    If all your dict keys are guaranteed to be strings, I would use a [`namedtuple`](https://docs.python.org/dev/library/collections.html#collections.namedtuple) and use sensible defaults in the returned value, instead of having to have the calling code second guess it like this. – lvc Jun 08 '15 at 08:33