web-dev-qa-db-fra.com

Comment mettre une variable dans Python docstring

J'essaie donc de créer une docstring "dynamique" qui ressemble à ceci:

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
"""

pour laisser fondamentalement la docstring pour @param animalType montrer ce que ANIMAL_TYPES a; de sorte que lorsque cette variable est mise à jour, la docstring sera mise à jour automatiquement.

Malheureusement, cela ne semble pas fonctionner. Est-ce que quelqu'un sait s'il existe un moyen d'y parvenir?

52
Jack Z

Les chaînes entre guillemets triples sont une grande chaîne. Rien n'est évalué à l'intérieur d'eux. Le % part fait partie de la chaîne. Vous devez le faire fonctionner sur la chaîne réelle.

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

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

Je ne suis pas certain que cela fonctionnera correctement, cependant; les docstrings sont un peu magiques. Cela pas fonctionnera; la docstring est évaluée au moment de la compilation (comme la première instruction de la fonction, étant donné qu'il s'agit d'un littéral de chaîne - une fois qu'il a le % dans ce n'est pas seulement un littéral de chaîne), le formatage de chaîne a lieu lors de l'exécution, donc __doc__ sera vide:

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

Si vous vouliez travailler de cette façon, vous auriez besoin de faire func.__doc__ %= {'ANIMAL_TYPES': ANIMAL_TYPES} une fois la fonction définie. Sachez que cela se briserait alors sur python -OO si vous ne l'avez pas vérifié __doc__ a été défini comme -OO supprime les docstrings.

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

Ce n'est pas la technique standard de toute façon; la technique standard consiste à référencer la constante appropriée: "Prend l'un des types d'animaux dans ANIMAL_TYPES", ou similaire.

17
Chris Morgan

Une façon de le faire serait d'utiliser un décorateur. Je ne sais pas ce que je ressens à ce sujet; J'ai en fait recherché des commentaires sur cette méthode et trouvé cette réponse , qui note à juste titre qu'elle pourrait masquer un problème de conception. Mais votre cas d'utilisation me semble sonore à première vue.

Dans tous les cas, voici une façon assez élégante d'obtenir le résultat que vous recherchez:

>>> 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

Vous pouvez également définir une docstring à l'aide de .__doc__

Par exemple:

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

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

Vous pouvez simplement utiliser références croisées dans votre docstring pour faire référence à la variable.

Alors:

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

Et dans le second:

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