Search code examples
pythondocstring

How do I write a docstring for the following Python function?


Suppose I have following function:

def get_matrix(*args, arbitrary=True):
    if arbitrary == True:
        return np.random.randint(-10,10, size=[args[0],args[1]])
    else:
        return np.array(args[0])

So the function either

  1. generates the matrix (if arbitrary == True); in this case it takes two int arguments.

or

  1. Converts array (if arbitrary == False) (represented by tuple, or list) into numpy's array

How do I write concise and readable dosctring for this function? (Preferably preserving numpy's docstring style) Numpy didn't have anything to say about how to document *args and **kwargs. (Or maybe they did, but I haven't found anything so far)


Solution

  • Whatever makes sense for your project. The generic term for *args is "positional arguments", and generally you're going to want to refer to them individually as "the nth positional argument". Keyword arguments **kwargs should usually be mentioned individually with acceptable keys and values on a case-by-case basis, unless the kwargs in your method is serving as a proxy for the kwargs in someone else's method, in which case you can also just write "Keyword arguments are the same as [other method], see that documentation for more details".


    The example you gave is a hard one in this case, mainly because it's kind of bad practice - a method should do one thing; if you have a method do two different things depending on the value of a flag, then why not just have two methods and make the caller call one of them explicitly? (further reading: PEP 20)

    Numpy's documentation standards seem to go even further, generally eschewing generic **kwargs entirely (in favor of explicitly named keywords), and preferring named positional arguments that you can refer to in docstrings. The document you linked doesn't provide explicit advice on the subject, but I would lean towards *args as the 'variable name' (keeping the asterisk there so as to denote that they are positional arguments) with integers as the value (note the plural), then note in the description explicitly that it's representing positional arguments. Alternatively, what I've done below, just list it as "positional arguments" explicitly (after all, this docstring format isn't useful for type hinting anyway).

    This is largely personal preference, but I would document your function as so:

    def get_matrix(*args, arbitrary=True):
        """
        If `arbitrary` is True (default), generates a random matrix, 
        with x and y bounds represented by the first two given 
        positional args, and returns it.
    
        If `arbitrary` is False, then instead coerces the first positional
        argument into a np.array, and returns that.
    
        parameters
        ----------
        positional args: ints
            purpose depends on the value of arbitrary (see above)
        arbitrary: bool
            determines the behavior of the function (see above)
    
        returns
        -------
        if arbitrary is true, a random 2D array of defined size.
        otherwise, the first positional argument coerced to a np.array
        """
        if arbitrary == True:
            return np.random.randint(-10,10, size=[args[0],args[1]])
        else:
            return np.array(args[0])