How to specify multiple return types in a function docstring in Python?

Alex Tereshenkov picture Alex Tereshenkov · Feb 6, 2019 · Viewed 7.2k times · Source

I am aware of the syntax used to build a docstring for Google style such as:

def function_with_types_in_docstring(param1, param2):
    """Example function with types documented in the docstring.

    `PEP 484`_ type annotations are supported. If attribute, parameter, and
    return types are annotated according to `PEP 484`_, they do not need to be
    included in the docstring:

    Args:
        param1 (int): The first parameter.
        param2 (str): The second parameter.

    Returns:
        bool: The return value. True for success, False otherwise.

    """

However, what if I have a function that can return multiple types depending on which branch of the code is executed? What would be a proper way to document this?

An example is below. What should be put into the Returns part?

def foo(x, y):
    """Dummy function.

    Args:
        x (int): integer
        y (int): integer

    Returns:
        list/dict: either list or a dict depending on...

    """
    if x > y:
        return [1, 2, 3]
    if x < y:
        return {1:2}

There is an example that shows two different possible return types:

def add2(a, b):
    """Add numbers or concatenate strings.

    Args:
      a (int/str): String or integer to be added
      b (int/str): String or integer to be added

    Returns:
      int/str: Result
    """
    pass

However, I wonder what would be the best way to provide both types AND description so that Napoleon would support it native and it would also be easy to read the docs.

Is using the int/str: %description% is the only way to handle multiple return types?

    Returns:
      int/str: integer if a > b and a string otherwise

Answer

Juan S&#225;nchez picture Juan Sánchez · Apr 4, 2020

If you want to use annotations to specify return types of different type depending of result of function, you can do it this way:

from typing import Type, Dict, Optional

def function(self) -> Optional[dict, str]:
    if self.result:
        return self.result
    else:
        return "Empty result"

Here you can find more info