web-dev-qa-db-ja.com

変数をPython docstringに入れる方法

だから私はこのようなものである「動的な」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
"""

基本的に@param animalTypeのdocstringにANIMAL_TYPESが持っているものをすべて表示させる。この変数が更新されると、docstringは自動的に更新されます。

残念ながら、動作しないようです。これを達成する方法があるかどうか誰かが知っていますか?

52
Jack Z

三重引用符で囲まれた文字列は、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}

ただし、これが正しく機能するかどうかはわかりません。 docstringsは少し魔法です。 これはnot機能します。 docstringはコンパイル時に評価されます(関数の最初のステートメントとして、それが文字列リテラルであることを考えると、%が含まれていると、それは単なる文字列リテラルではありません)。実行時に文字列のフォーマットが行われるため、 __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がdocstringを削除するため、__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の動物の種類の1つを取得します」など。

17
Chris Morgan

これを行う1つの方法は、デコレータを使用することです。私はこれについてどう感じているのかわかりません。実際にこの方法に関するコメントを検索したところ、 この答え が見つかりました。これは、設計の問題を隠す可能性があることを正しく示しています。しかし、あなたのユースケース一見私に聞こえます。

いずれにせよ、ここにあなたが探している結果を達成するためのかなりエレガントな方法があります:

>>> 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'
41
senderle

.__doc__を使用してdocstringを定義することもできます

例えば:

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

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

Docstringで cross-references を使用して変数を参照するだけです。

そう:

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

そして2番目に:

:param choice: can be one of :attr:`MY_CONST`
2
Dwayne