Skip to content

Instantly share code, notes, and snippets.

@doolio
Forked from dolph/good_docstrings.py
Last active November 10, 2023 14:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save doolio/ea4d5e96975005b523ed7c92c3626030 to your computer and use it in GitHub Desktop.
Save doolio/ea4d5e96975005b523ed7c92c3626030 to your computer and use it in GitHub Desktop.
pep257-good-python-docstrings-by-example
#!/usr/bin/env python3
"""Demonstrate high quality docstrings.
Module-level docstrings appear as the first "statement" in a
module. Remember, that while strings are regular Python statements,
comments are not, so an inline comment may precede the module-level
docstring.
After importing a module, you can access this special string object
through the ``__doc__`` attribute; yes, it's actually available as a
runtime attribute, despite not being given an explicit name! The
``__doc__`` attribute is also what is rendered when you call ``help()``
on a module, or really any other object in Python.
You can also document a package using the module-level docstring in the
package's ``__init__.py`` file in the package directory.
"""
def main() -> None:
"""Illustrate function-level docstring.
Note that all docstrings begin with a one-line summary. The summary
is written in the imperative mood ("do", "use", "find", "return",
"render", etc.) and ends with a period. For multi-line docstrings
the summary line is followed by a blank line. The method signature
is not, in any way, duplicated into the comments (that would be
difficult to maintain).
All subsequent paragraphs in a docstring are indented exactly the
same as the summary line. The same applies to the closing quotation
marks.
"""
docs = Documentation()
help(docs.__module__)
class Documentation:
"""Illustrate class-level docstring.
Classes use a special whitespace convention: a blank line follows
all docstrings whether one-line or multi-line. No other docstrings
should be followed by anything but code.
A blank line at the end of a multi-line docstring before the closing
quotation marks simply makes it easier for tooling to auto-format
paragraphs (wrapping them at 72 characters, per PEP8), without the
closing quotation marks interfering. For example, in Vim, you can
use `gqip` to "apply text formatting inside the paragraph." In
Emacs, the equivalent would be the `fill-paragraph` command. While
it's not required, the presence of a blank line is quite common and
much appreciated. Regardless, the closing quotation marks should
certainly be on a line by themselves.
"""
def __init__(self: 'Documentation') -> None:
"""Illustrate method-level docstring.
All public callables should have docstrings, including magic
methods like ``__init__()``.
You'll notice that all these docstrings are wrapped in triple
double quotes, as opposed to just "double quotes", 'single
quotes', or '''triple single quotes.''' This is a convention for
consistency and readability. However, there is an edge case
worth knowing about which I'll illustrate in just a moment.
"""
super().__init__()
def oneliner(self: 'Documentation') -> None:
"""One line docstring, including the quotation marks."""
return self.oneliner.__doc__
def backslashes(self: 'Documentation') -> None:
r"""Raw triple double quotes to escape \backslashes\."""
return self.backslashes.__doc__
def __unicode__(self: 'Documentation') -> None:
"""In Python 3, all strings are Ůňïčøđê by default.
The Unicode kind prefix necessary in Python 2 is no longer
necessary and should be removed to avoid confusion.
"""
return self.__unicode__.__doc__
if __name__ == '__main__':
# No need for a docstring here, but an inline comment explaining
# that this will only be executed when this module is run directly
# might be useful. Try running this module!
main()
$ pep257 --help
Usage: pep257 [options] [<file|dir>...]
Options:
--version show program's version number and exit
-h, --help show this help message and exit
-e, --explain show explanation of each error
-s, --source show source for each error
--select=<codes> choose the basic list of checked errors by specifying
which errors to check for (with a list of comma-
separated error codes). for example:
--select=D101,D202
--ignore=<codes> choose the basic list of checked errors by specifying
which errors to ignore (with a list of comma-separated
error codes). for example: --ignore=D101,D202
--convention=<name> choose the basic list of checked errors by specifying
an existing convention. for example:
--convention=pep257
--add-select=<codes> amend the list of errors to check for by specifying
more error codes to check.
--add-ignore=<codes> amend the list of errors to check for by specifying
more error codes to ignore.
--match=<pattern> check only files that exactly match <pattern> regular
expression; default is --match='(?!test_).*\.py' which
matches files that don't start with 'test_' but end
with '.py'
--match-dir=<pattern>
search only dirs that exactly match <pattern> regular
expression; default is --match-dir='[^\.].*', which
matches all dirs that don't start with a dot
-d, --debug print debug information
-v, --verbose print status information
--count print total number of errors to stdout
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment