Search code examples
pythonfunctionreturn

How does Python return multiple values from a function?


I have written the following code:

class FigureOut:
   def setName(self, name):
      fullname = name.split()
      self.first_name = fullname[0]
      self.last_name = fullname[1]

   def getName(self):
      return self.first_name, self.last_name

f = FigureOut()
f.setName("Allen Solly")
name = f.getName()
print (name)

I get the following Output:

('Allen', 'Solly')

Whenever multiple values are returned from a function in python, does it always convert the multiple values to a list of multiple values and then returns it from the function?

Is the whole process same as converting the multiple values to a list explicitly and then returning the list, for example in Java, as one can return only one object from a function in Java?


Solution

  • Since the return statement in getName specifies multiple elements:

    def getName(self):
       return self.first_name, self.last_name
    

    Python will return a container object that basically contains them.

    In this case, returning a comma separated set of elements creates a tuple. Multiple values can only be returned inside containers.

    Let's use a simpler function that returns multiple values:

    def foo(a, b):
        return a, b
    

    You can look at the byte code generated by using dis.dis, a disassembler for Python bytecode. For comma separated values w/o any brackets, it looks like this:

    >>> import dis
    >>> def foo(a, b):
    ...     return a,b        
    >>> dis.dis(foo)
      2           0 LOAD_FAST                0 (a)
                  3 LOAD_FAST                1 (b)
                  6 BUILD_TUPLE              2
                  9 RETURN_VALUE
    

    As you can see the values are first loaded on the internal stack with LOAD_FAST and then a BUILD_TUPLE (grabbing the previous 2 elements placed on the stack) is generated. Python knows to create a tuple due to the commas being present.

    You could alternatively specify another return type, for example a list, by using []. For this case, a BUILD_LIST is going to be issued following the same semantics as it's tuple equivalent:

    >>> def foo_list(a, b):
    ...     return [a, b]
    >>> dis.dis(foo_list)
      2           0 LOAD_FAST                0 (a)
                  3 LOAD_FAST                1 (b)
                  6 BUILD_LIST               2
                  9 RETURN_VALUE
    

    The type of object returned really depends on the presence of brackets (for tuples () can be omitted if there's at least one comma). [] creates lists and {} sets. Dictionaries need key:val pairs.

    To summarize, one actual object is returned. If that object is of a container type, it can contain multiple values giving the impression of multiple results returned. The usual method then is to unpack them directly:

    >>> first_name, last_name = f.getName()
    >>> print (first_name, last_name)
    

    As an aside to all this, your Java ways are leaking into Python :-)

    Don't use getters when writing classes in Python, use properties. Properties are the idiomatic way to manage attributes, for more on these, see a nice answer here.