How to specify that a parameter is a list of specific objects in Python docstrings

PythonPycharmDocstring

Python Problem Overview


I really like using docstrings in Python to specify type parameters when projects get beyond a certain size.

I'm having trouble finding a standard to use to specify that a parameter is a list of specific objects, e.g. in Haskell types I'd use [String] or [A].

Current standard (recognisable by PyCharm editor):

def stringify(listOfObjects):
    """
    :type listOfObjects: list
    """
    return ", ".join(map(str, listOfObjects))

What I'd prefer:

OPTION 1

def stringify(listOfObjects):
    """
    :type listOfObjects: list<Object>  
    """
    return ", ".join(map(str, listOfObjects))

OPTION 2

def stringify(listOfObjects):
    """
    :type listOfObjects: [Object]
    """
    return ", ".join(map(str, listOfObjects))

I suppose that wasn't a great example - the more relevant use case would be one where the objects in the list must be of a specific type.

BETTER EXAMPLE

class Food(Object):
    def __init__(self, calories):
        self.calories = calories

class Apple(Food):
    def __init__(self):
        super(self, 200)

class Person(Object):
    energy = 0
    def eat(foods):
        """
        :type foods: [Food]  # is NOT recognised by editor
        """
        for food in foods:
            energy += food.calories

So, other than the fact that I'm getting hungry, this example illustrates that if called with a list of the wrong kind of object, the code would break. Hence the importance of documenting not only that it needs a list, but that it needs a list of Food.

RELATED QUESTION https://stackoverflow.com/questions/6318814/how-can-i-tell-pycharm-what-type-a-parameter-is-expected-to-be Please note that I'm looking for a more specific answer than the one above.

Python Solutions


Solution 1 - Python

In comments section of PyCharm's manual there's a nice hint from developer:

#: :type: dict of (str, C)
#: :type: list of str

It works for me pretty well. Now it makes me wonder what's the best way to document parametrized classes in Python :).

Solution 2 - Python

As pointed out in the PyCharm docs, a (legacy, pre-PEP-484) way of doing this is using square brackets:

> list[Foo]: List of Foo elements > > dict[Foo, Bar]: Dict from Foo to Bar

list of str, as suggested in the accepted answer, does not work as expected in PyCharm.

Starting with Python 3.5 and the implementation of PEP-484, you can also use type hints, which may be nicely supported by your IDE/editor. How this is easily done in PyCharm is explained here.

In essence, to declare a list return type using type-hinting (Python >=3.5), you may do something like this:

from typing import List

"""
Great foo function.

:rtype: list[str]
"""
def foo() -> List[str]:
    return ['some string', 'some other string']

Here we declare (somewhat redundantly) that the function foo returns a list of strings, both in the type hint -> List[str] and in the docstring :rtype: list[str].

Other pre-declared types and more info can be found in the Python docs for typing.

Solution 3 - Python

in python

type([1,2,3]) == type(['a', 'b', 'c'])

you can also add a string to list of ints.

So for what you are trying to achieve PyCharm would have to magically check your whole code for what you are adding to the list before passing it as argument.

You can take a look at this question https://stackoverflow.com/questions/3391995/python-define-a-list-of-a-specific-type-of-object

Array module however allows only 'basic values'.

Only solution i can think of here is to create your own class that extends python list "FoodsList" that can check for type before adding element.

class Food():
    def __init__(self, calories):
        self.calories = calories

class FoodsList(list):
    #you can optionally extend append method here to validate type
    pass

def eat(foods):
    """
    :type foods: FoodsList
    """
    energy = 0
    for food in foods:
        energy += food.calories
    return energy


list = FoodsList()
list.append(Food(3))
list.append(Food(4))
print eat(list)

Solution 4 - Python

When writing docstrings in the google style you can do:

class ToDocument(object):
    """This is my Documentation.
    
    Args:
        typed_list (:obj:`list` of :obj:`str`): Description of typed list

    """
    ...

This also works pretty fine in sphinx, when combined with the napoleon-extension. Refer to the extension's doc for more examples on documentation.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlexView Question on Stackoverflow
Solution 1 - PythonMichael KorbakovView Answer on Stackoverflow
Solution 2 - PythonHendrikView Answer on Stackoverflow
Solution 3 - PythonfswView Answer on Stackoverflow
Solution 4 - PythonKimView Answer on Stackoverflow