'How to docstring kwargs and their expected types

What is the conventional way to express in a docstring the expected types of keyword arguments?

Or is this out of principle something I should not be doing at all? Google is suspiciously un-forthcoming on the subject.

(I am interested in doing this because I find that keeping track of expected types of all variables is very helpful as I code. I use PyCharm, which warns me when arguments have unexpected types, or when custom class attributes may be unresolved etc.)

However, I am finding that sometimes the list of possible keywrord arguments listed as

def foo(bar, parameter_1: int=1, paramter_2: str='', ...etc )

can become long and unreadable..

Consider the following code

class Person:
    def __init__(self, id: int, **kwargs):
        """
        :param id: social security number
        :type id: int
        :param **name: person's first name
        :type **name: str
        :param **age: person's age in years, rounded down
        :type **age: int
        """
        self.data = kwargs


bob = Person(123456568, name='Bob', age=48)
sally = Person(1245654568, name='Sally', age='22')

I would like to use the docstring to state the expected types. And I would like PyCharm to warn me that sally's age has the wrong type. Of course, I don't know if PyCharm even has the capacity to 'understand' that level of detail in the docstring. Nevertheless I'd like to know what the conventional way to do it is.

Other comments and suggestions about kwargs and docstrings also welcome.



Solution 1:[1]

Pycharm cannot warns you that your keywords has the wrong type but if you have the documentation panel open you can see the expected type if specified in the docstring. If not, the shortcut is ctr+q with caret at the function name. One time for a popup, two times to pin the documentation panel to the right.

You can alternativly raise an error if the type is incorrect.

After research and a lot of testing, here is everything I found. Take whatever you need :

from typing import Dict, Any
from warnings import warn


class Person:
    """
    a person
    """
    _ssn: int
    _data: Dict[str, Any]

    def __init__(self, ssn: int, *args, **kwargs) -> None:
        """
        Create an instance of Person

        :param ssn: social security number
        :type ssn: int
        :key name: person's first name, should be a str
        :key age: person's age in years, rounded down, should be an int
        :return: __init__ should return None
        :rtype: None
        """
        self._ssn = ssn
        if 'name' in kwargs:
            if type(kwargs['name']) is str:
                self._data['name'] = kwargs['name']
            else:
                raise TypeError("__init__() kwargs['name']: got {} but expected \
                type is str".format(type(kwargs["name"]).__name__))
        else:
            warn('This person have a default name', Warning)
            self._data['name'] = 'Smith'

        if 'age' in kwargs:
            if type(kwargs['age']) is int:
                self._data['age'] = kwargs['age']
            else:
                raise TypeError("__init__() kwargs['age']: got {} but expected \
                type is str".format(type(kwargs["age"]).__name__))
        else:
            warn('This person have a default age', Warning)
            self._data['age'] = 21

Instead of key you can use keyword.

This example provide :

  • Fully documented docstring used by PyCharm to generate Documentation
  • Type checking + Raise TypeError
  • Default values (bonus: Warn user that a default value is set)

Person

I suggest you adding @property.getter and @property.setter for accessing _id and _data. And the class attribute _data is overkill, you should replace it with _name and _age as you prefer default value instead of no value. Code here.

Warning : Shadows built-in name 'id'

I suggest ssn for social security number.

Sources: PyCharm 2018.3 Help

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1