3. Docstrings - minimal and full examples

In this section, we will systematically look at the docstrings for the various categories, modules, classes, and functions or methods. The aim is to clarify which sections and subsections are optional and which are mandatory, and what purpose they serve.

3.1. Module docstrings – minimal example

The minimum requirements for any Waterloo docstring are a valid Preamble with subsections profile and normative_sections, and a Contract.

Mandatory

Preamble – The Preamble represents the metadata of the docstring. It specifies what type of object is being documented (here profile: module) and which sections of the docstring are normative (normative_sections). Sections not listed here are not normative.

Mandatory and always normative

Contract – The Contract is the central section in which it is normatively documented what an object is used for, what it must be capable of, what preconditions must be fulfiled in order to use it, and what guarantees the object provides for the result. In the case of the module, there is a subsection named general.

"""
Preamble:
	profile:
		module
	normative_sections:
		Contract
Contract:
	general:
		|Must| demonstrate the minimal module docstring.
"""

Preamble

  • normative sections

    • Contract

Contract

  • general

    • Must demonstrate the minimal module docstring.

Module

test_docitem_module_minimal

3.2. Module docstrings – full example

The following example shows all possible sections and subsections in a module docstring. Some of the sections must always be listed as normative, some only under certain conditions (e.g. if they contain normativity keywords), while others are explicitly non-normative and must not be listed as normative.

Mandatory and always normative

Sections Contract

Optional and always normative

Sections Definitions, Public_classes, Public_functions, Public_types, Public_variables, Public_constants

Optional and normative under conditions

Sections Description and See_also are normative under certain conditions. If the description contains at least one normativity keyword in tokenized form, it must be listed under normative_sections – and vice versa. For See_also the following rule applies: Any validator will check whether the objects listed under See_also can be resolved. If the section is listed as normative, resolution failure leads to an error. If it is not listed, resolution failure only leads to a warning.

Optional and never normative

  • The Terminology and Notes sections are intended for human-readable explanations and notes. Since one of the basic principles of the Waterloo format is the strict separation between normative and informative content, certain sections must never be listed as normative.

  • Sections Class_overview and Function_overview are informative by design. Normative statements in *_overview sections would violate SSoT by introducing an additional normative source besides the class or function docstring. They would also violate LoII, as normative information would be distributed across multiple docstrings. The split between *_overview and Public_* sections is therefore necessary to satisfy BinNorm. Without this split, sections would contain a mixture of normative and informative content.

r"""
Preamble:
	profile:
		module
	normative_sections:
		Contract, Definitions, Public_classes, Public_functions,
		Public_types, Public_variables, Public_constants
Definitions:
	MyItem:
		This is a term named |term|`MyItem` in section "Definitions".
		This section is always normative and |must| be listed
		in "normative_sections". You can refer to this term by using the
		syntax token "|" + term + "|" followed by the referred term in
		backticks. Any validator will ensure that the terms you refer to
		by this token are defined in section "Definitions".
	My_Other_Item:
		Here is another example. Note that term names are Identifiers
		like variable names in most programming languages, restricted to
		letters, digits, and underscore.
Terminology:
	Fancy-Unicorn:
		The section "Terminology" allows to define terms in an informative
		manner. Typically, this subsection would start like
		"A Fancy-Unicorn is ..." followed by an explanation.
		|
		The section "Terminology" is never normative, never listed
		in "normative_sections" and does not contain normativity keywords
		in tokenized form.
		|
		As opposed to section "Definitions", any non-empty
		string is allowed, like here "Fancy-Unicorn".
		Take care, however, that the name does not collide with syntax rules
		of the intermediate document language (like reST in our case).
	
Contract:
	general:
		|Must| demonstrate all sections and subsections\
		and syntax tokens like backslash for continued lines.
		|Must| point out that logical lines are interpreted\
		as items, so here we have two logical lines, i.e. two items.
		This docstring |may| refer to |term|`MyItem` for demonstration purposes.
Description:
	The purpose of this module is to demonstrate waterloo docstrings
	on module level. A linter will accept this docstring, but
	coverage is not given, because the classes and function mentioned
	herein do not have docstrings.
	|
	The section "Description" allows free form text and the usage of
	the pipe character "|" in order to subdivide the text into paragraphs.
	|
	A section "Description" may be normative, but in this example it is not,
	since it does not contain normativity keywords in tokenized form.
Notes:
	What is it good for:
		Section "Notes" allows you to add informative content.
	What it is not good for:
		The section is never normative, it is never listed in
		"normative_sections" and it must not contain normativity
		keywords in tokenized form.
	Syntax:
		The section "Notes" is subdivided into subsections with
		user-defined labels like in this example "What is it good for:",
		"What it is not good for:" and "Syntax:"
Public_classes:
	MyClass
Class_overview:
	MyClass:
		Class for nothing
Public_functions:
	my_function
Function_overview:
	my_function:
		Important for demonstration but does nothing
Public_types:
	MyTypeAlias_t:
		|Must| represent a union of :wtrl_type:`float` and :wtrl_type:`int`.\
		This section is always normative. All relevant information about the\
		type alias is specified here, as type aliases do not provide their own\
		machine-verifiable docstrings.
Public_variables:
	my_variable:
		|Must| represent a value for this and that.\
		This section is always normative. All relevant information is specified\
		here, since variables do not have standardized, machine-verifiable\
		docstrings.
Public_constants:
	MY_CONSTANT:
		|Must| represent a constant value annotated as :wtrl_type:`Final`.\
		This section is always normative. All relevant information is specified\
		here, as constants do not provide their own machine-verifiable\
		docstrings.
		
See_also:
	test_docitem_module_minimal
"""

from typing import Final, TypeAlias

class MyClass:
	pass

def my_function() -> None:
	pass

MyTypeAlias_t: TypeAlias = float | int

my_variable : MyTypeAlias_t = 1.2345

MY_CONSTANT : Final[int] = 42

Preamble

  • normative sections

    • Contract, Definitions, Public classes, Public functions, Public types, Public variables, Public constants

Definitions

MyItem

This is a term named MyItem in section “Definitions”. This section is always normative and must be listed in “normative_sections”. You can refer to this term by using the syntax token “|” + term + “|” followed by the referred term in backticks. Any validator will ensure that the terms you refer to by this token are defined in section “Definitions”.

My_Other_Item

Here is another example. Note that term names are Identifiers like variable names in most programming languages, restricted to letters, digits, and underscore.

Terminology

Fancy-Unicorn

The section “Terminology” allows to define terms in an informative manner. Typically, this subsection would start like “A Fancy-Unicorn is …” followed by an explanation.

The section “Terminology” is never normative, never listed in “normative_sections” and does not contain normativity keywords in tokenized form.

As opposed to section “Definitions”, any non-empty string is allowed, like here “Fancy-Unicorn”. Take care, however, that the name does not collide with syntax rules of the intermediate document language (like reST in our case).

Contract

  • general

    • Must demonstrate all sections and subsections and syntax tokens like backslash for continued lines.

    • Must point out that logical lines are interpreted as items, so here we have two logical lines, i.e. two items.

    • This docstring may refer to MyItem for demonstration purposes.

Description

The purpose of this module is to demonstrate waterloo docstrings on module level. A linter will accept this docstring, but coverage is not given, because the classes and function mentioned herein do not have docstrings.

The section “Description” allows free form text and the usage of the pipe character “|” in order to subdivide the text into paragraphs.

A section “Description” may be normative, but in this example it is not, since it does not contain normativity keywords in tokenized form.

Notes

What is it good for

Section “Notes” allows you to add informative content.

What it is not good for

The section is never normative, it is never listed in “normative_sections” and it must not contain normativity keywords in tokenized form.

Syntax

The section “Notes” is subdivided into subsections with user-defined labels like in this example “What is it good for:”, “What it is not good for:” and “Syntax:”

Public classes

MyClass

Class overview

  • MyClass

    Class for nothing

Public functions

my_function

Function overview

  • my_function

    Important for demonstration but does nothing

Public types

  • MyTypeAlias_t

    Must represent a union of float and int. This section is always normative. All relevant information about the type alias is specified here, as type aliases do not provide their own machine-verifiable docstrings.

Public variables

  • my_variable

    Must represent a value for this and that. This section is always normative. All relevant information is specified here, since variables do not have standardized, machine-verifiable docstrings.

Public constants

  • MY_CONSTANT

    Must represent a constant value annotated as Final. This section is always normative. All relevant information is specified here, as constants do not provide their own machine-verifiable docstrings.

See also

test_docitem_module_minimal

Module

test_docitem_module_full

3.3. Class docstrings – minimal example

Many sections and subsections are equivalent to their counterparts in module docstring, but there are sections and subsections specific to class docstrings:

Mandatory and always normative

Contract.constructor – Each instance of a class is constructed in one or the other way. Therefore the Waterloo format demands a normative statement on the class constructor in section Contract.

class MyClass:
	"""
Preamble:
	profile:
		class
	normative_sections:
		Contract
Contract:
	general:
		|Must| demonstrate the minimal class docstring.
	constructor:
		|Must| be default-constructible
	"""
	pass

Preamble

  • normative sections

    • Contract

Contract

  • general

    • Must demonstrate the minimal class docstring.

  • constructor

    • Must be default-constructible

Class

MyClass

3.4. Class docstrings – full example

For demonstration purposes, the constructor signature in this example covers all supported ways to pass and accept parameters. Subsection Contract.constructor should describe the constructor parameters, how they are passed, and what the constructor does.

In addition to the sections described for module docstrings, class docstrings support the following optional sections and subsections.

Optional and always normative

Contract.traits – This optional subsection allows to declare certain semantic properties of a class. A limited set of trait identifiers is defined by this specification, including abstract for classes that are intended to serve primarily as base classes, and final for classes that are explicitly not meant to be extended. If the subsection is absent, the default is that the class is neither abstract nor final, meaning that it can be instantiated and may serve as a base class. The purpose of this subsection is to provide a normative way to express design intent, such as indicating that a class is part of an API surface only, or that it must not be used as a base for further extensions.

Derived_from – This optional section is related to Contract.traits. It normatively extends the public API of the documented class by declaring which base classes contribute public methods, types, variables, constants, or semantic guarantees. Validators verify that the classes listed in this section can be resolved using Python’s import mechanism. This serves as an anti-drift mechanism: if a base class is renamed, removed, or moved without updating this section, validation fails.

Public_methods – This section defines which methods of the class are part of the public API and is therefore normative.

Method_overview – This section is informative. It may be used to provide human-readable descriptions for selected methods, explaining their purpose or typical usage. This section may only be present if section Public_methods exists.

from typing import Any, Dict, Final, TypeAlias

# A base class which becomes part of the API.
class MyBaseClass:
	pass

# A private base class which prefer not o propagate as API.
class MyOtherBaseClass:
	pass

class MyClass(MyBaseClass,MyOtherBaseClass):
	"""
	Preamble:
		profile:
			class
		normative_sections:
			Contract, Definitions, Derived_from, Public_classes,
			Public_methods, Public_types, Public_variables, Public_constants
	Definitions:
		MyExampleItem:
			Define a term normatively. Same as for modules.
	Terminology:
		Fancy-Unicorn:
			Define a term informatively. Same as for modules.
	Contract:
		general:
			|Must| demonstrate the minimal class docstring.
		constructor:
			|Must| demand an int-valued positional parameter 'a'.
			|Must| demand a str-valued positional or keyword parameter 'b'.
			|Must| accept a float-valued positional or keyword parameter 'c'.
			|Must| demand a bool-valued keyword parameter 'd'.
			|Must| accept (variadic) keyword parameters and dispatch them as follows:
			|Must| accept a keyword parameter 'e' and assert it is str-valued (if present).
			The constructor |must| print all parameter values to 'stdout'.
		traits:
			final
	Derived_from:
		MyBaseClass
	Description:
		As for modules
	Notes:
		Purpose and Syntax:
			Same as for modules
	Public_classes:
		MyNestedClass
	Class_overview:
		MyNestedClass:
			Use this section for informative reminders what the class\
			is good for.
			Multiple lines are possible. Do not use Normativity Keywords.
	Public_methods:
		my_method
	Method_overview:
		my_method:
			Important for demonstration but does nothing
	Public_types:
		MyTypeAlias_t:
			Important type for annotations
	Public_variables:
		my_variable:
			A variable
	Public_constants:
		MY_CONSTANT:
			Another constant
	See_also:
		test_docitem_module_minimal
	"""

	class MyNestedClass:
		pass

	MyTypeAlias_t: TypeAlias = float | int

	my_variable: MyTypeAlias_t = 123

	MY_CONSTANT: Final[str] = "hello"

	def __init__(self, a: int, /, b: str, c: float = 1.23, *, d: bool, **kwargs: Any) -> None:
		# 'a' is positional-only
		# 'b' and 'c' are positional or keyword
		# 'd' is keyword-only
		
		print(a, b, c, d, kwargs)
		
		# Validation of 'e' from variadic parameters
		if "e" in kwargs:
			assert isinstance(kwargs["e"], str), "Parameter 'e' must be a string"
	def my_method(self, q : MyTypeAlias_t) -> None:
		pass

if __name__ == "__main__":
	m = MyClass(1,"hi",2.34,e="xyz",d=False)
	m = MyClass(2,"hi",3.45,e="yzx",d=False)
	m = MyClass(3,c=4.56,b="hi",d=True,e="zxy")

Preamble

  • normative sections

    • Contract, Definitions, Derived from, Public classes, Public methods, Public types, Public variables, Public constants

Definitions

MyExampleItem

Define a term normatively. Same as for modules.

Terminology

Fancy-Unicorn

Define a term informatively. Same as for modules.

Contract

  • general

    • Must demonstrate the minimal class docstring.

  • constructor

    • Must demand an int-valued positional parameter ‘a’.

    • Must demand a str-valued positional or keyword parameter ‘b’.

    • Must accept a float-valued positional or keyword parameter ‘c’.

    • Must demand a bool-valued keyword parameter ‘d’.

    • Must accept (variadic) keyword parameters and dispatch them as follows:

    • Must accept a keyword parameter ‘e’ and assert it is str-valued (if present).

    • The constructor must print all parameter values to ‘stdout’.

  • traits

    • final

Derived from

MyBaseClass

Description

As for modules

Notes

Purpose and Syntax

Same as for modules

Public classes

MyNestedClass

Class overview

  • MyNestedClass

    Use this section for informative reminders what the class is good for. Multiple lines are possible. Do not use Normativity Keywords.

Public methods

my_method

Method overview

  • my_method

    Important for demonstration but does nothing

Public types

Public variables

Public constants

See also

test_docitem_module_minimal

Class

MyClass

3.5. Function docstrings – minimal example

The following minimal example illustrates the essential structure of a function docstring. While deliberately simple, it highlights the sections that appear in every function docstring.

Apart from Preamble and Contract, which are already known from module and class docstrings, the following sections are present.

Mandatory and always normative

Parameters – Each subsection of this normative section represents a parameter of the function. The minimal example shown below does not define any parameters.

Returns – This section describes the return value. It is normative by definition, but it is up to the author whether to formulate requirements using Normativity Keywords or to keep the description purely descriptive.

Raises – Each subsection is labelled by an exception class and describes, normatively, the circumstances under which the exception is raised.

def spam() -> None:
	"""
	Preamble:
		profile:
			function
		normative_sections:
			Contract, Parameters, Returns, Raises
	Contract:
		general:
			|Must| demonstrate the minimal function docstring.
	Parameters:
	Returns:
		|None|
	Raises:
	"""
spam() -> None

Signature

test_docitem_function_minimal.spam(
) -> None

Preamble

  • normative sections

    • Contract, Parameters, Returns, Raises

Contract

  • general

    • Must demonstrate the minimal function docstring.

Parameters

Returns

None

Raises

<empty>
Function

spam

A typical way to populate the Raises section is as follows: An exception must be raised if it is a direct consequence of the function’s own behavior. An exception may be raised if it originates from a function called internally, potentially even from a different package.

Since the behavior of external functions may change over time (for example due to refactoring), the most conservative approach for such cases is to document exception propagation explicitly:

"""
Raises:
        BaseException:
                |May| propagate from functions ... and ...
"""

3.6. Function and method docstrings – intermediate example

The following example demonstrates a non-trivial method docstring that goes beyond the minimal structure, but does not yet use all available sections and subsections.

The method shown here is part of an abstract base class. It documents expected behavior, required preconditions, and possible failure modes, even though the method itself is not implemented in the base class.

This pattern is typical for framework-style code, where derived classes are expected to provide the actual implementation while adhering to a shared contract.

Most of the sections used in this example have already been introduced for module and class docstrings. However, the Contract section now contains a requires subsection, which is optional but normative as part of the contract.

The requires subsection should be used to specify the conditions that must be satisfied by the caller in order for the function to operate correctly.

The functionality of requires partially overlaps with Raises, as unmet prerequisites often lead to error conditions. Since such error behavior can also be described in Raises, the requires subsection itself is optional.

from typing import List, TypeAlias, Union

class tracer:
	pass

DocstringSubtree: TypeAlias = Union[str, List["DocstringSubtree"]]

class docitem_base:
	def parse(self,tr : tracer,subtree : DocstringSubtree) -> None:
		"""
		Preamble:
			profile:
				method
			normative_sections:
				Contract, Parameters, Returns, Raises
		Description:
			This docstring is located in the base class of all docitem
			node classes. The method is not implemented here and will
			raise an exception if it is invoked without a corresponding
			implementation in a derived class.
		Contract:
			general:
				|Must| parse a docstring subtree and create the related child items.
			requires:
				:wtrl_var:`subtree` |must| be a formally correct docstring subtree\
				from a Waterloo docstring; otherwise parsing will fail.
		Parameters:
			tr:
				The tracer for collecting diagnostics.
			subtree:
				A subtree of the tree matching this instance.
		Returns:
			|None|
		Raises:
			NotImplementedError:
				|Must| raise if not implemented in the derived class.
			RuntimeError:
				|Must| raise if the subtree does not match the expected format.
		"""
		raise NotImplementedError

Note that the function signature is not repeated in the docstring. Instead, it is included in the documentation via dedicated directives, ensuring that the rendered documentation remains complete without violating the Single Source of Truth principle (SSoT).

In this example, the function signature is annotated and treated as the sole authoritative source of type information, in accordance with the Single Source of Truth principle. This prevents the function signature and its documentation from drifting apart, supporting the Drift Prevention (DrPrv) principle.

As a consequence, the function signature must be explicitly included in the rendered documentation. This can be achieved using the directive

.. wtrl_function_signature:: test_docitem_function_medium.docitem_base.parse
parse(tr: tracer, subtree: str | typing.List[ForwardRef(‘DocstringSubtree’)]) -> None

For more complex type annotations, the directive

.. wtrl_function_signature_block:: test_docitem_function_medium.docitem_base.parse

may be used, which renders one line per parameter:

test_docitem_function_medium.docitem_base.parse(
tr: tracer
subtree: str | typing.List[ForwardRef(‘DocstringSubtree’)]
) -> None

While there is some flexibility in how the signature is presented, it must be included in order to make the documentation complete.

Signature

test_docitem_function_medium.docitem_base.parse(
tr: tracer
subtree: str | typing.List[ForwardRef(‘DocstringSubtree’)]
) -> None

Preamble

  • normative sections

    • Contract, Parameters, Returns, Raises

Description

This docstring is located in the base class of all docitem node classes. The method is not implemented here and will raise an exception if it is invoked without a corresponding implementation in a derived class.

Contract

  • general

    • Must parse a docstring subtree and create the related child items.

  • requires

    • subtree must be a formally correct docstring subtree from a Waterloo docstring; otherwise parsing will fail.

Parameters

  • tr

    The tracer for collecting diagnostics.

  • subtree

    A subtree of the tree matching this instance.

Returns

None

Raises

  • NotImplementedError

    • Must raise if not implemented in the derived class.

  • RuntimeError

    • Must raise if the subtree does not match the expected format.

Method

docitem_base.parse

3.7. Interlude – Docstring for inherited methods

The following example shows how to build a docstring for an inherited method. It is noticeable that, apart from the usual sections Preamble and Contract, there are no other mandatory sections. In particular, the sections Parameters, Returns, and Raises are missing because they are already included in the normative documentation of the base method. In section Contract, we see how this base method is explicitly referenced using the mandatory subsection base.

class docitem_list_of_symbols_base(docitem_base):
	def _parse(self, tr: tracer, refs: DocstringSubtree, pattern = str):
# Some implementation here...
#		...
		pass

class docitem_traits(docitem_list_of_symbols_base):
	def parse(self, tr: tracer, refs: DocstringSubtree) -> None:
		"""
		Preamble:
			profile:
				inherited_method
			normative_sections:
				Contract
		Contract:
			general:
				|Must| set rules-on-fail in the tracer and delegate\
				to method :wtrl_func:`._parse` in class\
				:wtrl_type:`docitem_list_of_symbols_base`.
			base:
				test_docitem_function_medium.docitem_base.parse
		"""
# Some implementation here...
#		...
		pass
test_docitem_function_medium.docitem_traits.parse(
tr: tracer
refs: str | typing.List[ForwardRef(‘DocstringSubtree’)]
) -> None

Signature

test_docitem_function_medium.docitem_traits.parse(
tr: tracer
refs: str | typing.List[ForwardRef(‘DocstringSubtree’)]
) -> None

Preamble

  • normative sections

    • Contract

Contract

Inherited_method

docitem_traits.parse

Apart from these differences, there are optional sections that are used in the same way as for modules, classes, and functions. So, all in all we have:

Mandatory and always normative

Subsection base is mandatory and normative. It unambiguously refers to the base method whose contract is authoritative for the derived method.

A derived method docstring may add additional normative statements, but it must remain substitutable for the base method.

  • Preconditions: A derived method must not strengthen the base method’s preconditions. In particular, any requirement that constrains valid inputs must be expressed in Contract.requires and must be compatible with the base method.

  • Guarantees: A derived method must preserve all guarantees of the base method. A derived method may provide additional guarantees by adding or refining Contract.ensures. Callers that only rely on the base contract may ignore such additional guarantees.

  • Failure modes documented in the base method must not be replaced by weaker guarantees. Additional failure modes must not occur for inputs that satisfy the base preconditions, unless they are explicitly permitted by the base contract.

Optional and always normative

  • Section Definitions

  • Subsection Contract.requires as discussed above under “Preconditions”

  • Subsection Contract.ensures as discussed above under “Guarantees”

Optional and normative under conditions

Sections Description and See_also

Optional and never normative

Sections Terminology and Notes

3.8. Function docstrings – full example

from __future__ import annotations
from typing import Final

_MAX_N: Final[int] = 20  # 20! fits into 64-bit signed; adjust as desired

def test() -> None:
	"""
Preamble:
	profile:
		function
	normative_sections:
		Contract, Parameters, Returns, Raises
Description:
	By this function we test the See_also section in factorial.
	Since :trl_label:`See_also` is normative (in this case)
	the docstring in the referred object must be a valid Waterloo string.
Contract:
	general:
		|Must| do nothing.
Parameters:
Returns:
	|None|
Raises:
	"""

def factorial(n: int) -> int:
	"""
Preamble:
	profile:
		function
	normative_sections:
		Definitions, Contract, Parameters, Returns, Raises, See_also

Definitions:
	factorial:
		For a non-negative integer n, factorial(n) is defined recursively by:
		factorial(0) = 1 and factorial(n) = n * factorial(n-1) for n > 0.
	positive:
		An integer x is called ``positive`` if x > 0.

Description:
	This function provides a simple, deterministic reference implementation.
	It is intended to demonstrate a full Waterloo function docstring with a
	clear contract and well-defined failure modes.

Terminology:
	recursion:
		The definition uses recursion; the implementation does not have to.

Contract:
	general:
		|Must| compute |term|`factorial` for the given argument.
		|Must| be thread-safe.
	requires:
		|var|`n` |must| be an integer.
		|var|`n` |must| be greater than or equal to 0.
		|var|`n` |must| be less than or equal to |var|`_MAX_N`.
	ensures:
		The return value |must| be an integer.
		If |var|`n` is 0, the result |must| be 1.
		If |var|`n` is greater than 0, the result |must| be |term|`positive`.
		The result |must| be divisible by |var|`n` for all |var|`n` > 0.

Parameters:
	n:
		Non-negative integer input.

Returns:
	The factorial value.

Raises:
	TypeError:
		|Must| raise if |var|`n` is not an |type|`int`.
	ValueError:
		|Must| raise if |var|`n` is negative.
	OverflowError:
		|Must| raise if |var|`n` is greater than |var|`_MAX_N`.
See_also:
	math.factorial, test
	"""
	if not isinstance(n, int):
		raise TypeError("factorial: n must be an int")
	if n < 0:
		raise ValueError("factorial: n must be >= 0")
	if n > _MAX_N:
		raise OverflowError(f"factorial: n must be <= {_MAX_N}")

	# Deterministic iterative implementation
	result = 1
	for k in range(2, n + 1):
		result *= k
	return result
factorial(n: int) -> int

Signature

test_docitem_function_full.factorial(
n: int
) -> int

Preamble

  • normative sections

    • Definitions, Contract, Parameters, Returns, Raises, See also

Definitions

factorial

For a non-negative integer n, factorial(n) is defined recursively by: factorial(0) = 1 and factorial(n) = n * factorial(n-1) for n > 0.

positive

An integer x is called positive if x > 0.

Description

This function provides a simple, deterministic reference implementation. It is intended to demonstrate a full Waterloo function docstring with a clear contract and well-defined failure modes.

Terminology

recursion

The definition uses recursion; the implementation does not have to.

Contract

  • general

    • Must compute factorial for the given argument.

    • Must be thread-safe.

  • requires

    • n must be an integer.

    • n must be greater than or equal to 0.

    • n must be less than or equal to _MAX_N.

  • ensures

    • The return value must be an integer.

    • If n is 0, the result must be 1.

    • If n is greater than 0, the result must be positive.

    • The result must be divisible by n for all n > 0.

Parameters

  • n

    Non-negative integer input.

Returns

The factorial value.

Raises

  • TypeError

    • Must raise if n is not an int.

  • ValueError

    • Must raise if n is negative.

  • OverflowError

    • Must raise if n is greater than _MAX_N.

See also

math.factorial, test

Function

factorial