2012-04-25 22 views
26

Así que estoy tratando de crear una cadena de documentación "dinámico", que es algo como esto:¿Cómo poner una variable en 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 
""" 

que vamos básicamente la cadena de documentación para @param animalType espectáculo lo tiene ANIMAL_TYPES; de modo que cuando esta variable se actualice, la docstring se actualizará automáticamente.

Lamentablemente, sin embargo, no parece funcionar ... ¿Alguien sabe si hay una manera de lograr esto?

Respuesta

12

Las cadenas de comillas triples son una cadena grande. Nada se evalúa dentro de ellos. La parte % es parte de la cadena. Tendría que tenerlo funcionando en la cadena real.

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

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

no estoy seguro de que esto va a funcionar correctamente, sin embargo; docstrings son un poco mágicos. Esto será no trabajo; la docstring se evalúa en tiempo de compilación (como la primera instrucción en la función, dado que es una cadena literal — una vez que tiene el %, no es solo una cadena literal), el formateo de cadena se lleva a cabo en tiempo de ejecución, por lo que __doc__ estará vacío :

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

Si quisiera trabajar de esta manera, que había necesidad de hacer func.__doc__ %= {'ANIMAL_TYPES': ANIMAL_TYPES} después de definir la función. Tenga en cuenta que esto se rompería en python -OO si no verificó que se haya definido __doc__, ya que -OO elimina las cadenas de documentos.

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

Esta no es la técnica estándar de todos modos; la técnica estándar es hacer referencia a la constante adecuada: "Toma uno de los tipos de animales en ANIMAL_TYPES", o similar.

+0

Gracias, Chris. ¿Puedo preguntar por qué '__doc__' estará vacío en el código que taché? ¡Gracias! –

+0

@JackZ: cubrió más ahora. –

+4

La razón por la que está vacío es porque la ** expresión ** ''foo% s'% 'bar'' no es una cadena literal, es una expresión que se evaluaría como una cadena. El compilador espera que una cadena literal real, como la primera cosa dentro del bloque, califique como una docstring. –

5

También puede definir una cadena de documentación utilizando .__doc__

Por ejemplo:

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

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

Una forma de hacer esto sería utilizar un decorador. No estoy seguro de cómo me siento sobre esto; De hecho, busqué comentarios sobre este método y encontré this answer, que indica con razón que podría enmascarar un problema de diseño. Pero su caso de uso me parece sonido a primera vista.

En cualquier caso, aquí es una forma bastante elegante para conseguir el resultado que buscas:

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

simplemente puede usar [referencias cruzadas] [1] en su doc-cadena para referirse a La variable.

Así:

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

Y en el segundo:

:param choice: can be one of :attr:`MY_CONST` 
+0

¿Puede alguien proporcionar un SSCE aclarando cómo escribir esto en un Python script? Vea también: http://sphinx-doc.org/domains.html#cross-referencing-python-objects y http://sphinx-doc.org/domains.html#python-roles – taz

Cuestiones relacionadas