Cómo poner una variable en la cadena de documentación de Python

Así que estoy tratando de crear una cadena de documentos “dinámica” que es algo como esto:

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

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

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

Las cadenas de comillas triples son una cadena grande. Nada es evaluado dentro de ellos. La parte % es todo parte de la cadena. Necesitarías tenerlo operando 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} 

Sin embargo, no estoy seguro de que esto funcione correctamente; Los cordajes son un poco mágicos. Esto no funcionará; la cadena de documentos se evalúa en tiempo de comstackción (como la primera instrucción de la función, dado que es una cadena literal, una vez que tiene el % en ella, no es solo una cadena literal), el formato de la cadena se realiza 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, tendría que hacer func.__doc__ %= {'ANIMAL_TYPES': ANIMAL_TYPES} después de definir la función. Tenga en cuenta que esto se interrumpiría en python -OO si no verifica que se __doc__ definido -OO , ya que -OO elimina las -OO documentación.

 >>> 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 apropiada: “Toma uno de los tipos de animales en ANIMAL_TYPES”, o similar.

Una forma de hacer esto sería usar un decorador. No estoy seguro de cómo me siento con esto; De hecho, busqué comentarios sobre este método y encontré esta respuesta , que señala correctamente que podría ocultar un problema de diseño. Pero su caso de uso me parece bien a primera vista.

En cualquier caso, esta es una manera bastante elegante de lograr el resultado que está buscando:

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

También puede definir una cadena de documentos usando .__doc__

Por ejemplo:

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

Simplemente puede usar referencias cruzadas en su cadena de documentos para referirse a la variable.

Asi que:

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

Y en el segundo:

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