Is it pythonic for a function to return multiple values?

In python, you can have a function return multiple values. Here's a contrived example:

def divide(x, y):
    quotient = x/y
    remainder = x % y
    return quotient, remainder  

(q, r) = divide(22, 7)

This seems very useful, but it looks like it can also be abused ("Well..function X already computes what we need as an intermediate value. Let's have X return that value also").

When should you draw the line and define a different method?


Asked by: Roman288 | Posted: 28-01-2022






Answer 1

Absolutely (for the example you provided).

Tuples are first class citizens in Python

There is a builtin function divmod() that does exactly that.

q, r = divmod(x, y) # ((x - x%y)/y, x%y) Invariant: div*y + mod == x

There are other examples: zip, enumerate, dict.items.

for i, e in enumerate([1, 3, 3]):
    print "index=%d, element=%s" % (i, e)

# reverse keys and values in a dictionary
d = dict((v, k) for k, v in adict.items()) # or 
d = dict(zip(adict.values(), adict.keys()))

BTW, parentheses are not necessary most of the time. Citation from Python Library Reference:

Tuples may be constructed in a number of ways:

  • Using a pair of parentheses to denote the empty tuple: ()
  • Using a trailing comma for a singleton tuple: a, or (a,)
  • Separating items with commas: a, b, c or (a, b, c)
  • Using the tuple() built-in: tuple() or tuple(iterable)

Functions should serve single purpose

Therefore they should return a single object. In your case this object is a tuple. Consider tuple as an ad-hoc compound data structure. There are languages where almost every single function returns multiple values (list in Lisp).

Sometimes it is sufficient to return (x, y) instead of Point(x, y).

Named tuples

With the introduction of named tuples in Python 2.6 it is preferable in many cases to return named tuples instead of plain tuples.

>>> import collections
>>> Point = collections.namedtuple('Point', 'x y')
>>> x, y = Point(0, 1)
>>> p = Point(x, y)
>>> x, y, p
(0, 1, Point(x=0, y=1))
>>> p.x, p.y, p[0], p[1]
(0, 1, 0, 1)
>>> for i in p:
...   print(i)
...
0
1

Answered by: Dominik662 | Posted: 01-03-2022



Answer 2

Firstly, note that Python allows for the following (no need for the parenthesis):

q, r = divide(22, 7)

Regarding your question, there's no hard and fast rule either way. For simple (and usually contrived) examples, it may seem that it's always possible for a given function to have a single purpose, resulting in a single value. However, when using Python for real-world applications, you quickly run into many cases where returning multiple values is necessary, and results in cleaner code.

So, I'd say do whatever makes sense, and don't try to conform to an artificial convention. Python supports multiple return values, so use it when appropriate.

Answered by: Blake363 | Posted: 01-03-2022



Answer 3

The example you give is actually a python builtin function, called divmod. So someone, at some point in time, thought that it was pythonic enough to include in the core functionality.

To me, if it makes the code cleaner, it is pythonic. Compare these two code blocks:

seconds = 1234
minutes, seconds = divmod(seconds, 60)
hours, minutes = divmod(minutes, 60)

seconds = 1234
minutes = seconds / 60
seconds = seconds % 60
hours = minutes / 60
minutes = minutes % 60

Answered by: Wilson242 | Posted: 01-03-2022



Answer 4

Yes, returning multiple values (i.e., a tuple) is definitely pythonic. As others have pointed out, there are plenty of examples in the Python standard library, as well as in well-respected Python projects. Two additional comments:

  1. Returning multiple values is sometimes very, very useful. Take, for example, a method that optionally handles an event (returning some value in doing so) and also returns success or failure. This might arise in a chain of responsibility pattern. In other cases, you want to return multiple, closely linked pieces of data---as in the example given. In this setting, returning multiple values is akin to returning a single instance of an anonymous class with several member variables.
  2. Python's handling of method arguments necessitates the ability to directly return multiple values. In C++, for example, method arguments can be passed by reference, so you can assign output values to them, in addition to the formal return value. In Python, arguments are passed "by reference" (but in the sense of Java, not C++). You can't assign new values to method arguments and have it reflected outside method scope. For example:

    // C++
    void test(int& arg)
    {
        arg = 1;
    }
    
    int foo = 0;
    test(foo); // foo is now 1!
    

    Compare with:

    # Python
    def test(arg):
        arg = 1
    
    foo = 0
    test(foo) # foo is still 0
    

Answered by: Kellan394 | Posted: 01-03-2022



Answer 5

It's definitely pythonic. The fact that you can return multiple values from a function the boilerplate you would have in a language like C where you need to define a struct for every combination of types you return somewhere.

However, if you reach the point where you are returning something crazy like 10 values from a single function, you should seriously consider bundling them in a class because at that point it gets unwieldy.

Answered by: Rubie874 | Posted: 01-03-2022



Answer 6

Returning a tuple is cool. Also note the new namedtuple which was added in python 2.6 which may make this more palatable for you: http://docs.python.org/dev/library/collections.html#collections.namedtuple

Answered by: Thomas542 | Posted: 01-03-2022



Answer 7

OT: RSRE's Algol68 has the curious "/:=" operator. eg.

INT quotient:=355, remainder;
remainder := (quotient /:= 113);

Giving a quotient of 3, and a remainder of 16.

Note: typically the value of "(x/:=y)" is discarded as quotient "x" is assigned by reference, but in RSRE's case the returned value is the remainder.

c.f. Integer Arithmetic - Algol68

Answered by: Kelsey913 | Posted: 01-03-2022



Answer 8

It's fine to return multiple values using a tuple for simple functions such as divmod. If it makes the code readable, it's Pythonic.

If the return value starts to become confusing, check whether the function is doing too much and split it if it is. If a big tuple is being used like an object, make it an object. Also, consider using named tuples, which will be part of the standard library in Python 2.6.

Answered by: Abigail598 | Posted: 01-03-2022



Answer 9

I'm fairly new to Python, but the tuple technique seems very pythonic to me. However, I've had another idea that may enhance readability. Using a dictionary allows access to the different values by name rather than position. For example:

def divide(x, y):
    return {'quotient': x/y, 'remainder':x%y }

answer = divide(22, 7)
print answer['quotient']
print answer['remainder']

Answered by: Daryl826 | Posted: 01-03-2022



Similar questions

python - pythonic way to apply function to object multiple times

I want to repeatedly sum over varying dimensions of a numpy ndarray eg. #what I've got sumOverDims = [6 4 2 1] ndarray = any n-dimensional numpy array #what I want to do ndarray.sum(6).sum(4).sum(2).sum(1) how can I do this without an ugly loop?


python - Most pythonic style for function calls with multiple params

Which is more Pythonic: Style one: self.partitions.append( Partition( self.current.bottom, self.current.lower, boundary)) Style two: self.partitions.append(Partition(self.current.upper, self.current.top, boundary))


python - Most pythonic way of function with no return?

A I couldn't find anything concerning in the PEP 8. I'm interested in your thoughts about the most pythonic syntax of function which have no return? Are there any reason to prevent functions without a return line(example 3)? Example 1: def foo(): print 'foo' return None Example 2: def foo(): print 'foo' pass Example 3:


python - Most Pythonic way to provide function metadata at compile time?

I am building a very basic platform in the form of a Python 2.7 module. This module has a read-eval-print loop where entered user commands are mapped to function calls. Since I am trying to make it easy to build plugin modules for my platform, the function calls will be from my Main module to an arbitrary plugin module. I'd like a plugin builder to be able to specify the command that he wants to trigger his function, so I'...


python - Pythonic way to reuse code inside only one function

My question refers to organizing code that is needed several times inside a function, and in no other place. Assuming the following use case: class A(object): def __init__(self, base): self.base = base def foo(self): result = self.base + 2 # Should go to an extra function. result = result * 4 if result > 10: result = result + 2 # Should go...


python - Pythonic way of retry running a function

This question already has answers here:


python - Most pythonic way to write high order function

It should be a very basic question but I wonder what's the most pythonic way to handle high order function. I have f and g already defined: def f(x): return x**2 def g(x): return x**3 def gen_func(f,g): def func(x): return f(x)+g(x) return func wanted_func = gen_func(f, g) or: import functools def gen_func(f,g,x): re...


python - pythonic way to apply function to object multiple times

I want to repeatedly sum over varying dimensions of a numpy ndarray eg. #what I've got sumOverDims = [6 4 2 1] ndarray = any n-dimensional numpy array #what I want to do ndarray.sum(6).sum(4).sum(2).sum(1) how can I do this without an ugly loop?


python - Is there a pythonic way to chain these function calls?

I have some code in which I end up with a list of binary functions and a list of values, and I need to chain the calls like so: funs = [..] vals = [..] result = funs[0](vals[0], funs[1](vals[1], .. funs[-1](vals[-2], vals[-1])))))..) For a simple example, if: funs = [operator.add, operator.mul] vals = [1, 2, 3] The...


python - Most Pythonic way to plot a vector function

I have a function calcField which, when given a numpy array with two elements representing a position, returns an array representing the electric field at that position. What is the most pythonic way to ask matplotlib to draw a vector field for this function? Currently I have this code working, but it feels against the spirit of numpy and is relatively unreadable. Y, X = np.mgrid[-3:3:100j, -3:...


python - Pythonic way of writing belongs function in two sets

I have two sets containing only strings, and I am trying to write a function like: def belongs(setA, setB): return True/False Definition: If a set, say setB has an item which contains (string contains) an item in setA, then I call setB belongs to setA. Some examples: ...


Most pythonic way to pass unknown amount of return values from one function as *args to another function in python

I am writing some Python code where the part of interest has the following setup: A function handle which is assigned to a function defined by the user. It must take at least one argument. Let's call it f Another function handle which is either None or assigned to the handle of some function define by the user. Let's call it get_extras. If it is not None


python - A pythonic way to insert a space before capital letters

I've got a file whose format I'm altering via a python script. I have several camel cased strings in this file where I just want to insert a single space before the capital letter - so "WordWordWord" becomes "Word Word Word". My limited regex experience just stalled out on me - can someone think of a decent regex to do this, or (better yet) is there a more pythonic way to do this that I'm missing?


python - Is there a more Pythonic way to merge two HTML header rows with colspans?

I am using BeautifulSoup in Python to parse some HTML. One of the problems I am dealing with is that I have situations where the colspans are different across header rows. (Header rows are the rows that need to be combined to get the column headings in my jargon) That is one column may span a number of columns above or below it and the words need to be appended or prepended based on the spanning. Below is a routine to d...


python - What is the pythonic way to share common files in multiple projects?

Lets say I have projects x and y in brother directories: projects/x and projects/y. There are some utility funcs common to both projects in myutils.py and some db stuff in mydbstuff.py, etc. Those are minor common goodies, so I don't want to create a single package for them. Questions arise about the whereabouts of such files, possible changes to PYTHONPATH, proper way to import, etc. What is th...


python - Pythonic ways to use 'else' in a for loop

This question already has answers here:


python - pythonic way to compare compound classes?

I have a class that acts as an item in a tree: class CItem( list ): pass I have two trees, each with CItem as root, each tree item has some dict members (like item._test = 1). Now i need to compare this trees. I can suggest to overload a comparison operator for CItem: class CItem( list ): def __eq__( self, other ): # first compare items as lists if not list.__eq...


python - Pythonic URL Parsing

There are a number of questions about how to parse a URL in Python, this question is about the best or most Pythonic way to do it. In my parsing I need 4 parts: the network location, the first part of the URL, the path and the filename and querystring parts. http://www.somesite.com/base/first/secon...


list - Pythonic way to get some rows of a matrix

I was thinking about a code that I wrote a few years ago in Python, at some point it had to get just some elements, by index, of a list of lists. I remember I did something like this: def getRows(m, row_indices): tmp = [] for i in row_indices: tmp.append(m[i]) return tmp Now that I've learnt a little bit more since then, I'd use a list comprehension like this:


python - What is the Pythonic way to write this loop?

for jr in json_reports: jr['time_created'] = str(jr['time_created'])


python - How do you make this code more pythonic?

Could you guys please tell me how I can make the following code more pythonic? The code is correct. Full disclosure - it's problem 1b in Handout #4 of this machine learning course. I'm supposed to use newton's algorithm on the two data sets for fitting a logistic hypothesis. But they use matlab & I'm using scipy ...


python - Pythonic Swap of 2 lists elements

I found that I have to perform a swap in python and I write something like this: arr[first], arr[second] = arr[second], arr[first] I suppose this is not so pythonic. Does somebody know how to do a swap in python more elegant? EDIT: I think another example will show my doubts: self.memberlist[someindexA], self.memberlist[someindexB] = self.memberlist[som...






Still can't find your answer? Check out these communities...



PySlackers | Full Stack Python | NHS Python | Pythonist Cafe | Hacker Earth | Discord Python



top