Подтвердить что ты не робот

Как поместить переменную в docstring Python

Итак, я пытаюсь создать "динамическую" docstring, которая выглядит примерно так:

ANIMAL_TYPES = ["mammals", "reptiles", "other"]

def func(animalType):
""" This is a sample function.

    @param animalType: "It takes one of these animal types %s" % ANIMAL_TYPES
"""

чтобы в принципе позволить docstring для @param animalType показать, что ANIMAL_TYPES имеет; так что, когда эта переменная будет обновлена, docstring будет обновляться автоматически.

К сожалению, однако, похоже, что это не работает... Кто-нибудь знает, есть ли способ достичь этого?

4b9b3361

Ответ 1

Строки в тройных кавычках - это одна большая строка. Ничто не оценивается внутри них. Часть % является частью строки. Вам нужно, чтобы он работал с реальной строкой.

def func(animalType):
    """
    This is a sample function.

    @param animalType: "It takes one of these animal types %(ANIMAL_TYPES)s"
    """ % {'ANIMAL_TYPES': ANIMAL_TYPES}

Я не уверен, что это будет работать должным образом; Строки документа немного волшебны. Это не будет работать; строка документа оценивается во время компиляции (как первый оператор в функции, учитывая, что он является строковым литералом - как только он получил в нем % а не просто строковый литерал), форматирование строки происходит во время выполнения, поэтому __doc__ будет пустым:

>>> def a(): 'docstring works'
... 
>>> a.__doc__
'docstring works'
>>> def b(): "formatted docstring doesn't work %s" % ':-('
... 
>>> b.__doc__
>>> 

Если вы хотите работать таким образом, вам нужно будет выполнить func.__doc__ %= {'ANIMAL_TYPES': ANIMAL_TYPES} после определения функции. Имейте в python -OO что это может python -OO если вы не проверите, что __doc__ был определен, так как -OO удаляет строки документации.

>>> def c(): "formatted docstring works %s"
... 
>>> c.__doc__
"formatted docstring works %s"
>>> c.__doc__ %= 'after'
>>> c.__doc__
"formatted docstring works after"

В любом случае, это не стандартная техника; стандартным методом является ссылка на соответствующую константу: "Принимает один из типов животных в ANIMAL_TYPES" или аналогичный.

Ответ 2

Один из способов сделать это - использовать декоратор. Я не уверен, как я к этому отношусь; Я действительно искал комментарий к этому методу и нашел этот ответ, который по праву отмечает, что он может маскировать проблему дизайна. Но ваш случай использования кажется мне на первый взгляд.

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

>>> def docstring_parameter(*sub):
...     def dec(obj):
...         obj.__doc__ = obj.__doc__.format(*sub)
...         return obj
...     return dec
... 
>>> @docstring_parameter('Ocean')
... def foo():
...     '''My Docstring Lies Over The {0}'''
...     pass
... 
>>> @docstring_parameter('Sea')
... def bar():
...     '''My Docstring Lies Over The {0}'''
...     pass
... 
>>> @docstring_parameter('Docstring', 'Me')
... def baz():
...     '''Oh Bring Back My {0} To {1}'''
...     pass
... 
>>> foo.__doc__
'My Docstring Lies Over The Ocean'
>>> bar.__doc__
'My Docstring Lies Over The Sea'
>>> foo.__doc__
'My Docstring Lies Over The Ocean'
>>> baz.__doc__
'Oh Bring Back My Docstring To Me'

Ответ 3

Вы также можете определить docstring с помощью .__doc__

Например:

>>> def f():
      pass
>>> x = 1
>>> y = "docstring"

>>> f.__doc__ = "%s string %s" % (x, y)
>>> print(f.__doc__)
1 string docstring

Ответ 4

Вы можете просто использовать перекрестные ссылки в вашей строке документации для ссылки на переменную.

Так:

:param animalType: It takes one of these :data:'animal types<ANIMAL_TYPES>'

И во втором:

:param choice: can be one of :attr:'MY_CONST'