руководство по документации pandas#

О строках документации и стандартах#

Строка документации Python — это строка, используемая для документирования модуля, класса, функции или метода Python, чтобы программисты могли понять, что он делает, не читая детали реализации.

Также распространённой практикой является автоматическая генерация онлайн (html) документации из строк документации. Sphinx служит этой цели.

Следующий пример дает представление о том, как выглядит строка документации:

def add(num1, num2):
    """
    Add up two integer numbers.

    This function simply wraps the ``+`` operator, and does not
    do anything interesting, except for illustrating what
    the docstring of a very simple function looks like.

    Parameters
    ----------
    num1 : int
        First number to add.
    num2 : int
        Second number to add.

    Returns
    -------
    int
        The sum of ``num1`` and ``num2``.

    See Also
    --------
    subtract : Subtract one integer from another.

    Examples
    --------
    >>> add(2, 2)
    4
    >>> add(25, 0)
    25
    >>> add(10, -10)
    0
    """
    return num1 + num2

Существуют некоторые стандарты относительно docstrings, которые делают их более удобочитаемыми и позволяют легко экспортировать их в другие форматы, такие как html или pdf.

Первые соглашения, которым должна следовать каждая строка документации Python, определены в PEP-257.

Поскольку PEP-257 довольно широк, существуют и другие, более конкретные стандарты. В случае pandas следует соглашению о строках документации NumPy. Эти соглашения объясняются в этом документе:

numpydoc — это расширение Sphinx для поддержки соглашения о строках документации NumPy.

Стандарт использует reStructuredText (reST). reStructuredText — это язык разметки, позволяющий кодировать стили в простых текстовых файлах. Документацию по reStructuredText можно найти в:

pandas имеет вспомогательные инструменты для совместного использования строк документации между связанными классами, см. Совместное использование строк документации.

В оставшейся части этого документа будут обобщены все вышеуказанные рекомендации, а также предоставлены дополнительные соглашения, специфичные для проекта pandas.

Написание документационной строки#

Общие правила#

Строки документации должны быть определены с тремя двойными кавычками. Не должно быть пустых строк до или после строки документации. Текст начинается в следующей строке после открывающих кавычек. Закрывающие кавычки находятся на отдельной строке (то есть не в конце последнего предложения).

В редких случаях в строках документации используются стили reST, такие как жирный текст или курсив, но обычно используется встроенный код, который представлен между обратными кавычками. Следующее считается встроенным кодом:

  • Имя параметра

  • Код Python, модуль, функция, встроенная функция, тип, литерал… (например, os, list, numpy.abs, datetime.date, True)

  • Класс pandas (в форме :class:`pandas.Series`)

  • Метод pandas (в форме :meth:`pandas.Series.sum`)

  • Функция pandas (в виде :func:`pandas.to_datetime`)

Примечание

Чтобы отобразить только последний компонент связанного класса, метода или функции, добавьте к нему префикс ~. Например, :class:`~pandas.Series` будет ссылаться на pandas.Series но отображать только последнюю часть, Series в качестве текста ссылки. См. Синтаксис перекрестных ссылок Sphinx подробности.

Хорошо:

def add_values(arr):
    """
    Add the values in ``arr``.

    This is equivalent to Python ``sum`` of :meth:`pandas.Series.sum`.

    Some sections are omitted here for simplicity.
    """
    return sum(arr)

Плохо:

def func():

    """Some function.

    With several mistakes in the docstring.

    It has a blank like after the signature ``def func():``.

    The text 'Some function' should go in the line after the
    opening quotes of the docstring, not in the same line.

    There is a blank line between the docstring and the first line
    of code ``foo = 1``.

    The closing quotes should be in the next line, not in this one."""

    foo = 1
    bar = 2
    return foo + bar

Раздел 1: краткое содержание#

Краткое описание — это одно предложение, которое выражает, что делает функция, в сжатой форме.

Краткое описание должно начинаться с заглавной буквы, заканчиваться точкой и помещаться в одну строку. Оно должно выражать, что делает объект, без предоставления подробностей. Для функций и методов краткое описание должно начинаться с инфинитива глагола.

Хорошо:

def astype(dtype):
    """
    Cast Series type.

    This section will provide further details.
    """
    pass

Плохо:

def astype(dtype):
    """
    Casts Series type.

    Verb in third-person of the present simple, should be infinitive.
    """
    pass
def astype(dtype):
    """
    Method to cast Series type.

    Does not start with verb.
    """
    pass
def astype(dtype):
    """
    Cast Series type

    Missing dot at the end.
    """
    pass
def astype(dtype):
    """
    Cast Series type from its current type to the new type defined in
    the parameter dtype.

    Summary is too verbose and doesn't fit in a single line.
    """
    pass

Раздел 2: расширенное резюме#

Расширенное резюме предоставляет подробности о том, что делает функция. Оно не должно углубляться в детали параметров или обсуждать примечания по реализации, которые помещаются в другие разделы.

Пустая строка оставляется между кратким и расширенным описанием. Каждый абзац в расширенном описании заканчивается точкой.

Расширенное описание должно предоставлять детали о том, почему функция полезна и её варианты использования, если она не слишком общая.

def unstack():
    """
    Pivot a row index to columns.

    When using a MultiIndex, a level can be pivoted so each value in
    the index becomes a column. This is especially useful when a subindex
    is repeated for the main index, and data is easier to visualize as a
    pivot table.

    The index level will be automatically removed from the index when added
    as columns.
    """
    pass

Раздел 3: параметры#

Подробности параметров будут добавлены в этом разделе. Этот раздел имеет заголовок "Параметры", за которым следует строка с дефисами под каждой буквой слова "Параметры". Перед заголовком раздела оставляется пустая строка, но не после, и не между строкой со словом "Параметры" и строкой с дефисами.

После заголовка каждый параметр в сигнатуре должен быть задокументирован, включая *args и **kwargs, но не self.

Параметры определяются их именем, за которым следует пробел, двоеточие, еще один пробел и тип (или типы). Обратите внимание, что пробел между именем и двоеточием важен. Типы не определяются для *args и **kwargs, но должен быть определен для всех остальных параметров. После определения параметра требуется строка с описанием параметра, которая имеет отступ и может состоять из нескольких строк. Описание должно начинаться с заглавной буквы и заканчиваться точкой.

Для аргументов ключевых слов со значением по умолчанию, значение по умолчанию будет указано после запятой в конце типа. Точная форма типа в этом случае будет «int, по умолчанию 0». В некоторых случаях может быть полезно объяснить, что означает аргумент по умолчанию, что можно добавить после запятой «int, по умолчанию -1, означает все процессоры».

В случаях, когда значение по умолчанию None, что означает, что значение не будет использоваться. Вместо "str, default None", предпочтительнее писать "str, optional". Когда None используется значение, мы сохраним форму "str, default None". Например, в df.to_csv(compression=None), None не является используемым значением, а означает, что сжатие необязательно, и сжатие не используется, если не предоставлено. В этом случае мы будем использовать "str, optional". Только в случаях, таких как func(value=None) и None используется таким же образом, как 0 или foo будет использоваться, тогда мы укажем "str, int или None, по умолчанию None".

Хорошо:

class Series:
    def plot(self, kind, color='blue', **kwargs):
        """
        Generate a plot.

        Render the data in the Series as a matplotlib plot of the
        specified kind.

        Parameters
        ----------
        kind : str
            Kind of matplotlib plot.
        color : str, default 'blue'
            Color name or rgb code.
        **kwargs
            These parameters will be passed to the matplotlib plotting
            function.
        """
        pass

Плохо:

class Series:
    def plot(self, kind, **kwargs):
        """
        Generate a plot.

        Render the data in the Series as a matplotlib plot of the
        specified kind.

        Note the blank line between the parameters title and the first
        parameter. Also, note that after the name of the parameter ``kind``
        and before the colon, a space is missing.

        Also, note that the parameter descriptions do not start with a
        capital letter, and do not finish with a dot.

        Finally, the ``**kwargs`` parameter is missing.

        Parameters
        ----------

        kind: str
            kind of matplotlib plot
        """
        pass

Типы параметров#

При указании типов параметров можно напрямую использовать встроенные типы данных Python (предпочтительнее использовать тип Python, а не более многословные строки, целые числа, логические значения и т.д.):

  • int

  • float

  • str

  • bool

Для сложных типов определите подтипы. Для dict и tuple, так как присутствует более одного типа, мы используем скобки для удобства чтения типа (фигурные скобки для dict и обычные скобки для tuple):

  • список целых чисел

  • словарь {str : int}

  • кортеж из (str, int, int)

  • кортеж из (str,)

  • набор строк

В случае, когда есть только набор допустимых значений, перечислите их в фигурных скобках, разделённых запятыми (с последующим пробелом). Если значения упорядочены и имеют порядок, перечислите их в этом порядке. В противном случае перечислите значение по умолчанию первым, если оно есть:

  • {0, 10, 25}

  • {‘simple’, ‘advanced’}

  • {‘low’, ‘medium’, ‘high’}

  • {'cat', 'dog', 'bird'}

Если тип определен в модуле Python, модуль должен быть указан:

  • datetime.date

  • datetime.datetime

  • decimal.Decimal

Если тип находится в пакете, модуль также должен быть указан:

  • numpy.ndarray

  • scipy.sparse.coo_matrix

Если тип является типом pandas, также укажите pandas, за исключением Series и DataFrame:

  • Series

  • DataFrame

  • pandas.Index

  • pandas.Categorical

  • pandas.arrays.SparseArray

Если точный тип не важен, но должен быть совместим с массивом NumPy, можно указать array-like. Если принимается любой тип, который можно итерировать, можно использовать iterable:

  • array-like

  • итерируемый объект

Если принимается более одного типа, разделяйте их запятыми, кроме последних двух типов, которые нужно разделить словом ‘или’:

  • int или float

  • float, decimal.Decimal или None

  • str или список str

Если None является одним из допустимых значений, он всегда должен быть последним в списке.

Для оси принято использовать что-то вроде:

  • axis : {0 или 'index', 1 или 'columns', None}, по умолчанию None

Раздел 4: возвращает или генерирует#

Если метод возвращает значение, оно будет задокументировано в этом разделе. Также если метод выводит свои результаты.

Заголовок раздела будет определён так же, как "Параметры". С именами "Возвращает" или "Генерирует", за которыми следует строка с таким количеством дефисов, сколько букв в предыдущем слове.

Документация возвращаемого значения также похожа на параметры. Но в этом случае имя не будет предоставлено, если метод не возвращает или не выдает более одного значения (кортеж значений).

Типы для "Returns" и "Yields" такие же, как для "Parameters". Также описание должно заканчиваться точкой.

Например, с одним значением:

def sample():
    """
    Generate and return a random number.

    The value is sampled from a continuous uniform distribution between
    0 and 1.

    Returns
    -------
    float
        Random number generated.
    """
    return np.random.random()

С более чем одним значением:

import string

def random_letters():
    """
    Generate and return a sequence of random letters.

    The length of the returned string is also random, and is also
    returned.

    Returns
    -------
    length : int
        Length of the returned string.
    letters : str
        String of random letters.
    """
    length = np.random.randint(1, 10)
    letters = ''.join(np.random.choice(string.ascii_lowercase)
                      for i in range(length))
    return length, letters

Если метод возвращает свое значение:

def sample_values():
    """
    Generate an infinite sequence of random numbers.

    The values are sampled from a continuous uniform distribution between
    0 and 1.

    Yields
    ------
    float
        Random number generated.
    """
    while True:
        yield np.random.random()

Раздел 5: см. также#

Этот раздел используется, чтобы сообщить пользователям о функциональности pandas, связанной с документируемой. В редких случаях, если связанные методы или функции вообще не могут быть найдены, этот раздел можно пропустить.

Очевидным примером будет head() и tail() методы. Как tail() делает эквивалентное действие как head() но в конце Series или DataFrame вместо начала, хорошо дать пользователям знать об этом.

Чтобы дать интуитивное представление о том, что можно считать связанным, вот несколько примеров:

  • loc и iloc, так как они делают одно и то же, но в одном случае предоставляют индексы, а в другом - позиции

  • max и min, так как они делают противоположное

  • iterrows, itertuples и items, так как пользователь, ищущий метод для итерации по столбцам, может легко попасть в метод для итерации по строкам, и наоборот

  • fillna и dropna, так как оба метода используются для обработки пропущенных значений

  • read_csv и to_csv, так как они дополняют друг друга

  • merge и join, так как один является обобщением другого

  • astype и pandas.to_datetime, так как пользователи могут читать документацию astype чтобы знать, как преобразовать в дату, и способ сделать это с помощью pandas.to_datetime

  • where связано с numpy.where, так как его функциональность основана на этом

При решении, что является связанным, в основном следует использовать здравый смысл и думать о том, что может быть полезно для пользователей, читающих документацию, особенно для менее опытных.

При сравнении с другими библиотеками (в основном numpy), используйте имя модуля сначала (не псевдоним, как np). Если функция находится в модуле, который не является основным, например scipy.sparse, укажите полный модуль (например, scipy.sparse.coo_matrix).

Этот раздел имеет заголовок "См. также" (обратите внимание на заглавные буквы S и A), за которым следует строка с дефисами и предшествует пустая строка.

После заголовка мы добавим строку для каждого связанного метода или функции, затем пробел, двоеточие, еще один пробел и краткое описание, которое иллюстрирует, что делает этот метод или функция, почему он актуален в данном контексте и какие ключевые различия существуют между документированной функцией и ссылкой. Описание также должно заканчиваться точкой.

Обратите внимание, что в разделах "Returns" и "Yields" описание находится на строке после типа. В этом разделе, однако, оно находится на той же строке, с двоеточием между ними. Если описание не помещается на той же строке, оно может продолжаться на других строках, которые должны иметь больший отступ.

Например:

class Series:
    def head(self):
        """
        Return the first 5 elements of the Series.

        This function is mainly useful to preview the values of the
        Series without displaying the whole of it.

        Returns
        -------
        Series
            Subset of the original series with the 5 first values.

        See Also
        --------
        Series.tail : Return the last 5 elements of the Series.
        Series.iloc : Return a slice of the elements in the Series,
            which can also be used to return the first or last n.
        """
        return self.iloc[:5]

Раздел 6: примечания#

Это необязательный раздел, используемый для заметок о реализации алгоритма или для документирования технических аспектов поведения функции.

Можете пропустить это, если только вы не знакомы с реализацией алгоритма или обнаружили какое-то неинтуитивное поведение при написании примеров для функции.

Этот раздел следует тому же формату, что и раздел расширенного описания.

Раздел 7: примеры#

Это один из самых важных разделов документации, несмотря на то, что он находится в последней позиции, так как часто люди лучше понимают концепции на примерах, чем через точные объяснения.

Примеры в строках документации, помимо иллюстрации использования функции или метода, должны быть валидным кодом на Python, который возвращает заданный вывод детерминированным способом и который пользователи могут копировать и запускать.

Примеры представлены как сессия в терминале Python. >>> используется для представления кода. ... используется для продолжения кода с предыдущей строки. Вывод представлен сразу после последней строки кода, генерирующего вывод (без пустых строк между ними). Комментарии, описывающие примеры, могут быть добавлены с пустыми строками до и после них.

Способ представления примеров следующий:

  1. Импорт необходимых библиотек (кроме numpy и pandas)

  2. Создать данные, необходимые для примера

  3. Показать очень простой пример, который дает представление о наиболее распространенном случае использования

  4. Добавьте примеры с пояснениями, иллюстрирующие, как параметры могут использоваться для расширенной функциональности

Простой пример может быть:

class Series:

    def head(self, n=5):
        """
        Return the first elements of the Series.

        This function is mainly useful to preview the values of the
        Series without displaying all of it.

        Parameters
        ----------
        n : int
            Number of values to return.

        Return
        ------
        pandas.Series
            Subset of the original series with the n first values.

        See Also
        --------
        tail : Return the last n elements of the Series.

        Examples
        --------
        >>> ser = pd.Series(['Ant', 'Bear', 'Cow', 'Dog', 'Falcon',
        ...                'Lion', 'Monkey', 'Rabbit', 'Zebra'])
        >>> ser.head()
        0   Ant
        1   Bear
        2   Cow
        3   Dog
        4   Falcon
        dtype: object

        With the ``n`` parameter, we can change the number of returned rows:

        >>> ser.head(n=3)
        0   Ant
        1   Bear
        2   Cow
        dtype: object
        """
        return self.iloc[:n]

Примеры должны быть максимально краткими. В случаях, когда сложность функции требует длинных примеров, рекомендуется использовать блоки с заголовками, выделенными жирным шрифтом. Используйте двойную звезду ** чтобы сделать текст жирным, как в **this example**.

Соглашения для примеров#

Предполагается, что код в примерах всегда начинается с этих двух строк, которые не показаны:

import numpy as np
import pandas as pd

Любой другой модуль, используемый в примерах, должен быть явно импортирован, по одному на строку (как рекомендуется в PEP 8#imports) и избегайте псевдонимов. Избегайте избыточных импортов, но если необходимо, импорты из стандартной библиотеки идут первыми, затем сторонние библиотеки (например, matplotlib).

При иллюстрации примеров с одним Series использовать имя ser, и если иллюстрируя одним DataFrame использовать имя df. Для индексов, idx является предпочтительным названием. Если набор однородных Series или DataFrame используется, назовите их ser1, ser2, ser3… или df1, df2, df3… Если данные неоднородны и требуется более одной структуры, назовите их осмысленно, например df_main и df_to_join.

Данные, используемые в примере, должны быть максимально компактными. Рекомендуемое количество строк — около 4, но выберите число, которое имеет смысл для конкретного примера. Например, в head метод требует, чтобы значение было больше 5, чтобы показать пример со значениями по умолчанию. Если выполнить mean, мы могли бы использовать что-то вроде [1, 2, 3], поэтому легко увидеть, что возвращаемое значение является средним.

Для более сложных примеров (например, группировки) избегайте использования данных без интерпретации, таких как матрица случайных чисел со столбцами A, B, C, D… Вместо этого используйте осмысленный пример, который облегчает понимание концепции. Если это не требуется примером, используйте названия животных, чтобы сохранить примеры согласованными. И их числовые свойства.

При вызове метода, ключевые аргументы head(n=3) предпочтительнее позиционных аргументов head(3).

Хорошо:

class Series:

    def mean(self):
        """
        Compute the mean of the input.

        Examples
        --------
        >>> ser = pd.Series([1, 2, 3])
        >>> ser.mean()
        2
        """
        pass


    def fillna(self, value):
        """
        Replace missing values by ``value``.

        Examples
        --------
        >>> ser = pd.Series([1, np.nan, 3])
        >>> ser.fillna(0)
        [1, 0, 3]
        """
        pass

    def groupby_mean(self):
        """
        Group by index and return mean.

        Examples
        --------
        >>> ser = pd.Series([380., 370., 24., 26],
        ...               name='max_speed',
        ...               index=['falcon', 'falcon', 'parrot', 'parrot'])
        >>> ser.groupby_mean()
        index
        falcon    375.0
        parrot     25.0
        Name: max_speed, dtype: float64
        """
        pass

    def contains(self, pattern, case_sensitive=True, na=numpy.nan):
        """
        Return whether each value contains ``pattern``.

        In this case, we are illustrating how to use sections, even
        if the example is simple enough and does not require them.

        Examples
        --------
        >>> ser = pd.Series('Antelope', 'Lion', 'Zebra', np.nan)
        >>> ser.contains(pattern='a')
        0    False
        1    False
        2     True
        3      NaN
        dtype: bool

        **Case sensitivity**

        With ``case_sensitive`` set to ``False`` we can match ``a`` with both
        ``a`` and ``A``:

        >>> s.contains(pattern='a', case_sensitive=False)
        0     True
        1    False
        2     True
        3      NaN
        dtype: bool

        **Missing values**

        We can fill missing values in the output using the ``na`` parameter:

        >>> ser.contains(pattern='a', na=False)
        0    False
        1    False
        2     True
        3    False
        dtype: bool
        """
        pass

Плохо:

def method(foo=None, bar=None):
    """
    A sample DataFrame method.

    Do not import NumPy and pandas.

    Try to use meaningful data, when it makes the example easier
    to understand.

    Try to avoid positional arguments like in ``df.method(1)``. They
    can be all right if previously defined with a meaningful name,
    like in ``present_value(interest_rate)``, but avoid them otherwise.

    When presenting the behavior with different parameters, do not place
    all the calls one next to the other. Instead, add a short sentence
    explaining what the example shows.

    Examples
    --------
    >>> import numpy as np
    >>> import pandas as pd
    >>> df = pd.DataFrame(np.random.randn(3, 3),
    ...                   columns=('a', 'b', 'c'))
    >>> df.method(1)
    21
    >>> df.method(bar=14)
    123
    """
    pass

Советы по прохождению доктестов для ваших примеров#

Получение примеров, проходящих тесты документации в скрипте валидации, иногда может быть сложным. Вот некоторые моменты, на которые стоит обратить внимание:

  • Импортировать все необходимые библиотеки (кроме pandas и NumPy, они уже импортированы как import pandas as pd и import numpy as np) и определите все переменные, которые вы используете в примере.

  • Старайтесь избегать использования случайных данных. Однако случайные данные могут быть допустимы в некоторых случаях, например, если документируемая функция работает с вероятностными распределениями, или если объём данных, необходимый для придания результату функции смысла, слишком велик, так что создание его вручную очень обременительно. В таких случаях всегда используйте фиксированное случайное начальное значение, чтобы сделать сгенерированные примеры предсказуемыми. Пример:

    >>> np.random.seed(42)
    >>> df = pd.DataFrame({'normal': np.random.normal(100, 5, 20)})
    
  • Если у вас есть фрагмент кода, который охватывает несколько строк, вам нужно использовать '...' на продолженных строках:

    >>> df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], index=['a', 'b', 'c'],
    ...                   columns=['A', 'B'])
    
  • Если вы хотите показать случай, когда возникает исключение, вы можете сделать:

    >>> pd.to_datetime(["712-01-01"])
    Traceback (most recent call last):
    OutOfBoundsDatetime: Out of bounds nanosecond timestamp: 712-01-01 00:00:00
    

    Важно включить «Traceback (most recent call last):», но для самой ошибки достаточно только имени ошибки.

  • Если есть небольшая часть результата, которая может варьироваться (например, хэш в представлении объекта), вы можете использовать ... чтобы представить эту часть.

    Если вы хотите показать, что s.plot() возвращает объект matplotlib AxesSubplot, это приведёт к провалу doctest

    >>> s.plot()
    
    

    Однако вы можете сделать (обратите внимание на комментарий, который нужно добавить)

    >>> s.plot()  
    
    

Графики в примерах#

В pandas есть некоторые методы, возвращающие графики. Для отображения графиков, сгенерированных примерами в документации, .. plot:: директива существует.

Чтобы использовать его, поместите следующий код после заголовка "Примеры", как показано ниже. График будет сгенерирован автоматически при сборке документации.

class Series:
    def plot(self):
        """
        Generate a plot with the ``Series`` data.

        Examples
        --------

        .. plot::
            :context: close-figs

            >>> ser = pd.Series([1, 2, 3])
            >>> ser.plot()
        """
        pass

Совместное использование строк документации#

pandas имеет систему для совместного использования строк документации с небольшими вариациями между классами. Это помогает нам сохранять строки документации согласованными, сохраняя ясность для пользователя. Это достигается ценой некоторой сложности при написании.

Каждый общий docstring будет иметь базовый шаблон с переменными, например {klass}. Переменные, заполняемые позже с использованием doc декоратор. Наконец, строки документации также могут быть дополнены с помощью doc декоратор.

В этом примере мы создадим родительскую строку документации обычным способом (это похоже на pandas.core.generic.NDFrame. Тогда у нас будет два дочерних элемента (как pandas.core.series.Series и pandas.core.frame.DataFrame). Мы заменим имена классов в этой строке документации.

class Parent:
    @doc(klass="Parent")
    def my_function(self):
        """Apply my function to {klass}."""
        ...


class ChildA(Parent):
    @doc(Parent.my_function, klass="ChildA")
    def my_function(self):
        ...


class ChildB(Parent):
    @doc(Parent.my_function, klass="ChildB")
    def my_function(self):
        ...

Результирующие строки документации являются

>>> print(Parent.my_function.__doc__)
Apply my function to Parent.
>>> print(ChildA.my_function.__doc__)
Apply my function to ChildA.
>>> print(ChildB.my_function.__doc__)
Apply my function to ChildB.

Примечание:

  1. Мы «добавляем» родительскую строку документации к дочерним строкам документации, которые изначально пусты.

Наши файлы часто содержат модуль-уровень _shared_doc_kwargs с некоторыми общими значениями подстановки (такими как klass, axes, и т.д.).

Вы можете заменить и добавить за один раз с помощью чего-то вроде

@doc(template, **_shared_doc_kwargs)
def my_function(self):
    ...

где template может поступать из модуля уровня _shared_docs словарь сопоставления имён функций с строками документации. По возможности мы предпочитаем использовать doc, поскольку процесс написания документации немного ближе к обычному.

См. pandas.core.generic.NDFrame.fillna для примера шаблона, и pandas.core.series.Series.fillna и pandas.core.generic.frame.fillna для заполненных версий.