For a detailed description of the numpydoc
standard, see numpy’s actual description of the style. This should be read by each developer to make sure we understand exactly what is required and what other options we have while documenting. Here is a summary of the key components of that document:
numpydoc
style docstrings are written in restructured text. They are composed of a short description of the object followed by a few required and optional sections. For functions and methods, these sections are:
Required
Optional
The sections for a class are the same, except instead of a Returns
section there is an Attribute
section that defines all attributes of the class.
A docstring is a string that starts on the first new line immediately after the declaration of a function or a class. Like the body of the function or class, the docstring must be indented 4 spaces. Typically, a docstring is contained within a block string, set off by tripe quotes “”” as shown below:
def func(a, b):
"""
This is a docstring for a function
""""
class MyNewClass(object):
"""
This is a docstring for this class.
"""
Docstrings provide a way for developers to document their code inline. This is very useful for many reasons, among which are:
help
on a particular object.numpydoc
style docstringsnumpydoc
style docstrings are written using restructured text (aka rst: the markup used in sphinx documents), using a special structure. While any restructured text is valid in a numpydoc style docstring, the only required restructured text element is knowing how to define a section. In our docstrings, we will denote sections using the following syntax:
Section name
------------
The key elements are a line containing only the name of the section followed be another line containing only minus signs (-
) underneath each character of the section name.
Using this syntax, a numpydoc
style docstring for a function or method is made up of the following elements:
Parameters
that explains the object’s input parametersReturns
that explains that function’s outputExamples
: This section is optional, but strongly recommended and encouraged within QuantEcon (it may be required at some time in the future). Within the section we would include one or more examples for how to use the obejct.Notes
: This section provides additional details that help the user or fellow developer understand the function, but were not included in the short description at the beginning. This might include a description of the algorithm or mathematics underlying the function.References
: If any journal articles, books, or other publications or 3rd party code were consulted when writing the function, this should be documented in this section.Raises
: if the function/class might raise an exception when called, the exception along with cases under which the exception is raised should be documented.See Also
: if the function/class is related to another object, we should specify this relation in a See Also
section.Below is an example of such a docstring
def func(a, b, c=3):
"""
Short description of what the function accomplishes
Parameters
----------
a : scalar(float)
Explanation of what a is used for within the function
b : array_like(float)
Explanation of what a is used for within the function
c : scalar(int), optional(default=3)
Explanation of what c is used for within the function
Returns
-------
ret1 : type of ret1
Explanation of the first object returned
ret2 : type of ret2
Explanation of the second object returned
Notes
-----
Any implementation notes that help understand how/why the function
was written the way it was. This section is optional.
References
----------
In this section we include any references to papers/articles/other
reading material or other code that we referenced when writing the
function
Examples
--------
>>> a = 130; b = [10, 20, 30]
>>> func(a, b)
<function output copied and pasted>
Raises
------
ValueError
If any parameters are equal to `None.`
"""
There are a few additional points to mention here:
c
above)self
in the list of parameters.The numpydoc
standard for documenting classes is very similar. The key components are (this all goes the first line of the docstring that is below the line containing the class
keyword)
Parameters
section that describes the parameters for the class’s __init__
functionAttributes
section that describes all the attributes of the class. This replaces the Returns
section we saw above for functions and methods.Methods
that are implemented specifically for this class.Remark There is often overlap between the parameter list and the attribute list. To avoid repetition attributes already discussed in the parameter list can be entered in the attributes list in the form a, b, c : seeParameters
. An example is given below.
Below I will provide some examples. These are copied and pasted from the source of some code we are already using, or will soon be using from within QuantEcon. For additional examples, see these two references:
def poly_inds(d, mu, inds=None):
"""
Build indices specifying all the Cartesian products of Chebychev
polynomials needed to build Smolyak polynomial
Parameters
----------
d : scalar(int)
The number of dimensions in grid / polynomial
mu : scalar(int)
The parameter mu defining the density of the grid
inds : list(list(int)), optional(default=None)
The Smolyak indices for parameters d and mu. Should be computed
by calling `smol_inds(d, mu)`. If None is given, the indices
are computed using this function call
Returns
-------
phi_inds : array_like(int, ndim=2)
A two dimensional array of integers where each row specifies a
new set of indices needed to define a Smolyak basis polynomial
Notes
-----
This function uses smol_inds and phi_chain. The output of this
function is used by build_B to construct the B matrix
"""
class SmolyakGrid(object):
"""
This class currently takes a dimension and a degree of polynomial
and builds the Smolyak Sparse grid. We base this on the work by
Judd, Maliar, Maliar, and Valero (2013).
Parameters
----------
d : scalar(int)
The number of dimensions in the grid
mu : scalar(int) or array_like(int, ndim=1, length=d)
The "density" parameter for the grid
Attributes
----------
d, mu : see Parameters
lb : array_like(float, ndim=2)
This is an array of the lower bounds for each dimension
ub : array_like(float, ndim=2)
This is an array of the upper bounds for each dimension
cube_grid : array_like(float, ndim=2)
The Smolyak sparse grid on the domain :math:`[-1, 1]^d`
grid: : array_like(float, ndim=2)
The sparse grid, transformed to the user-specified bounds for
the domain
inds : list(list(int))
This is a lists of lists that contains all of the indices
B : array_like(float, ndim=2)
This is the B matrix that is used to do lagrange interpolation
B_L : array_like(float, ndim=2)
Lower triangle matrix of the decomposition of B
B_U : array_like(float, ndim=2)
Upper triangle matrix of the decomposition of B
Examples
--------
>>> s = SmolyakGrid(3, 2)
>>> s
Smolyak Grid:
d: 3
mu: 2
npoints: 25
B: 0.65% non-zero
>>> ag = SmolyakGrid(3, [1, 2, 3])
>>> ag
Anisotropic Smolyak Grid:
d: 3
mu: 1 x 2 x 3
npoints: 51
B: 0.68% non-zero
"""
Method example
--------------
def interpolate(self, pts, interp=True, deriv=False):
"""
Basic Lagrange interpolation, with optional first derivatives
(gradient)
Parameters
----------
pts : array_like(float, ndim=2)
A 2d array of points on which to evaluate the function. Each
row is assumed to be a new d-dimensional point. Therefore, pts
must have the same number of columns as ``si.SGrid.d``
interp : bool, optional(default=false)
Whether or not to compute the actual interpolation values at pts
deriv : bool, optional(default=false)
Whether or not to compute the gradient of the function at each
of the points. This will have the same dimensions as pts, where
each column represents the partial derivative with respect to
a new dimension.
Returns
-------
rets : list(array(float))
A list of arrays containing the objects asked for. There are 2
possible objects that can be computed in this function. They will,
if they are called for, always be in the following order:
1. Interpolation values at pts
2. Gradient at pts
If the user only asks for one of these objects, it is returned
directly as an array and not in a list.
References
----------
This is a stripped down port of ``dolo.SmolyakBasic.interpolate``
"""