Reputation: 18532
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 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.
Upvotes: 77
Views: 79609
Reputation: 5310
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.
Upvotes: 25
Reputation: 1497
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.
Upvotes: 2
Reputation: 2177
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 :).
Upvotes: 66
Reputation: 3695
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 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)
Upvotes: 4