Более 1 строки документации для одного модуля / функции и т.д.?
Вопрос
Я использую python 3.1.
Возможно ли создать более 1 строки документа для одного модуля или функции?Я создаю программу, и я намереваюсь иметь несколько строк документации с категорией для каждой.Я намерен предоставить другим людям программу, чтобы они могли ею пользоваться, и, чтобы упростить задачу как программистам, так и непрограммистам, я помещаю ссылку на строку docstring для документации внутри самой программы.
Чтобы быть более конкретным, у меня есть меню в программе / модуле в качестве интерфейса, и одна из опций позволит получить доступ к docstring модуля для документации по программе.Таким образом, если это возможно, я хочу создать несколько строк документации для классификации различных типов документации.Таким образом, пользователям будет проще, если они захотят просмотреть какую-то часть документации.
например.первая строка документа содержит инструкции по использованию программы.Вторая строка документа содержит информацию о том, как работает одна часть программы.Третья строка документа содержит информацию о том, как работает другая часть.и т.д.
Возможно ли это?И если да, то как вы ссылаетесь на них?
Обновления:Добавлен комментарий.
Моя первоначальная мысль состояла в том, чтобы на самом деле иметь более одной строки документации в смысле:
def foo():
"""docstring1: blah blah blah"""
"""docstring2: blah blah blah"""
pass # Insert code here
Тогда был бы какой-нибудь код, который я мог бы использовать, чтобы ссылаться на каждую из этих строк документации.Итак, я предполагаю, что тогда это невозможно?
Решение
Я не рекомендую пытаться делать что-то сложное со строками документов.Лучше всего сохранить строки документации простыми и сделать что-то еще, если вы хотите сделать доступными множество различных вариантов документации.
Если вы действительно хотите сделать то, что вы описали, я предлагаю вам использовать теги для разграничения разделов внутри docstrings .Вот так:
def foo(bar, baz):
"""Function foo()
* Summary:
Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them.
* Developers:
When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests.
* Testers:
When you test foo, be sure to try negative values for baz.
"""
pass # code would go here
Тогда вы можете довольно легко разбить свою строку на фрагменты, и когда пользователь выбирает пункт меню, показывать только соответствующие фрагменты.
s = foo.__doc__ # s now refers to the docstring
lst = s.split("\n* ")
section = [section for section in lst if section.startswith("Developers")][0]
print(section) # prints the "Developers" section
Таким образом, когда вы работаете в интерактивной оболочке Python, вы можете сказать "help (foo)", и вы увидите все строки документации.И вы не меняете фундаментальное поведение базовой части Python, которое могло бы вывести из себя других людей, пытающихся изучить ваш код.
Вы также могли бы сделать что-то еще более простое:просто создайте большой глобальный словарь строк документации для разных целей и обновляйте его из исходного кода для каждой новой вещи.
doc_developers = {} doc_testers = {}
def foo(bar, baz):
"""Function foo()
Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them."
pass # code goes here
doc_developers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests."
doc_testers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests."
Самое большое, что мне в этом не нравится, это то, что если вы измените имя функции foo, вам нужно будет изменить его в нескольких местах:оказавшись в фактическом def
и один раз в строке обновления словаря.Но в основном вы могли бы исправить это, написав функцию:
def doc_dict = {} # this will be a dict of dicts
doc_dict["developers"] = {}
doc_dict["testers"] = {}
def doc_update(fn, d):
name = fn.__name__
for key, value in d.items():
doc_dict[key][name] = value
def foo(bar, baz):
"""Function foo()
Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them."
pass # code goes here
d = { "developers": "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests.",
"testers": " When you test foo, be sure to try negative values for baz."}
doc_update(foo, d)
Вероятно, есть способ превратить doc_update() в декоратор, но сейчас у меня нет времени.
Другие советы
Вы хотите рассмотреть возможность использования декораторы чтобы чисто выполнять то, что ~ unutbu предлагает для функций:добавление отдельного поля для каждого из них.Например:
def human_desc(description):
def add_field(function):
function.human_desc = description
return function
return add_field
Это то, что human_desc
в действии это выглядело бы как:
@human_desc('This function eggfoobars its spam.')
def eggfoobar(spam):
"Apply egg, foo and bar to our spam metaclass object stuff."
print spam
Объяснение
Как док объясняет, этот бит кода эквивалентен следующему:
def eggfoobar(spam):
"Apply egg, foo and bar to our spam metaclass object stuff."
print spam
eggfoobar = human_desc('This function eggfoobars its spam.')(eggfoobar)
и human_desc('This function eggfoobars its spam.')
возвращает следующую функцию:
def add_field(function):
function.human_desc = 'This function eggfoobars its spam.'
return function
Как вы можете видеть human_desc
является функцией, которая генерирует приведенный выше декоратор для значения description
вы передаете в качестве аргумента.Сам декоратор представляет собой функцию, которая принимает функцию, подлежащую оформлению (модификации), и возвращает ее оформленной (в данном случае, то есть с добавлением этого бита дополнительных метаданных).Короче говоря, это эквивалентно:
def eggfoobar(spam):
"Apply egg, foo and bar to our spam metaclass object stuff."
print spam
eggfoobar.human_desc = 'This function eggfoobars its spam.'
Синтаксис, однако, намного чище и менее подвержен ошибкам.
Очевидно, что в любом случае, то, что вы получаете, это:
>>> print eggfoobar.human_desc
This function eggfoobars its spam.
Вместо использования функции вы могли бы использовать класс с usage
и extra
определены атрибуты.Например,
class Foo(object):
'''Here is the function's official docstring'''
usage='All about the usage'
extra='How another part works'
def __call__(self):
# Put the foo function code here
pass
foo=Foo()
Вы бы назвали это как обычно: foo()
,
и вы можете получить официальную строку документа и альтернативную строку документа, подобную этой:
print foo.__doc__
print foo.usage
print foo.extra
Вы также можете присоединять дополнительные атрибуты к простым функциям (вместо использования класса, как я сделал выше), но я думаю, что синтаксис немного уродливее:
def foo():
pass
foo.usage='Usage string'
foo.extra='Extra string'
Кроме того, модули тоже являются объектами.Они так же легко могут иметь дополнительные атрибуты:
Если вы определяете константы модуля
USAGE='''blah blah'''
EXTRA='''meow'''
Затем, когда вы импортируете модуль:
import mymodule
Вы можете получить доступ к официальным и альтернативным разделам документации с помощью
mymodule.__doc__
mymodule.USAGE
mymodule.EXTRA
Вы можете заменить __doc__
атрибут, если вы хотите иметь более одной возможной строки документа, но, пожалуйста, подумайте о том, чтобы сделать исходную строку документа достаточно гибкой для всех типов.
Модуль - это набор классов / функций / модулей.Таким образом, его строка документа дает вводную информацию о том, что она содержит.
Класс docstring сообщает, что представляет собой класс, а его методы docstrings сообщают, что это за методы so.Класс служит одной цели, а методы выполняют одну задачу, поэтому у них должна быть одна строка документа.
Функции выполняют одну вещь, поэтому для них должно быть достаточно одной доктрины.
Я не вижу, для какой цели будет достаточно нескольких строк документации.Может быть, ваш модуль большой.Разделите на подмодули и в строке документации для модуля укажите подмодули.