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.
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.
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.
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): """
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.
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 :
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With