Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

python - 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.

like image 550
levraininjaneer Avatar asked Dec 03 '17 11:12

levraininjaneer


People also ask

What are the three types of docstrings?

Docstrings can be further broken up into three major categories: Class Docstrings: Class and class methods. Package and Module Docstrings: Package, modules, and functions. Script Docstrings: Script and functions.

What does __ doc __ mean in Python?

The __doc__ attribute Each Python object (functions, classes, variables,...) provides (if programmer has filled it) a short documentation which describes its features. You can access it with commands like print myobject.

What is a docstring explain with suitable example?

Multi-line docstrings consist of a summary line just like a one-line docstring, followed by a blank line, followed by a more elaborate description. The summary line may be on the same line as the opening quotes or on the next line. The example below shows a multi-line docstring. def my_function(arg1): """

How do you write a NumPy style docstring?

The docstring in NumPy style consists of several sections. At a minimum, start with a short (one-line) summary of what the function does. If useful, add a few extra lines of extended summary. Then add a section describing the parameters and their types, and another section for the return values.


1 Answers

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

like image 139
Dorian Turba Avatar answered Sep 22 '22 09:09

Dorian Turba