Más de 1 docstrings para un solo módulo / función, etc.

Estoy usando python 3.1.

¿Es posible crear más de 1 cadena de documentos para un solo módulo o función? Estoy creando un progtwig, y ​​tengo la intención de tener varias cadenas de documentos con una categoría para cada uno. Tengo la intención de darles el progtwig a otras personas para que puedan usarlo, y para facilitar las cosas tanto a los progtwigdores como a los no progtwigdores, pongo una referencia a la cadena de documentación para la documentación dentro del progtwig en sí.

Para ser más específico, tengo un menú en el progtwig / módulo como una interfaz, y una de las opciones permitirá el acceso a la documentación del módulo para la documentación del progtwig. Por lo tanto, si es posible, quiero hacer varias cadenas de documentación para clasificar diferentes tipos de documentación. Así que sería más fácil para los usuarios si quisieran ver alguna parte de la documentación.

p.ej. La primera cadena de documentos contiene instrucciones sobre cómo usar el progtwig. La segunda cadena de documentos contiene información sobre cómo funciona una parte del progtwig. La tercera cadena de documentos contiene información sobre cómo funciona otra parte. etc.

es posible? Y si es así, ¿cómo se hace referencia a ellos?

Actualizaciones: Agregado un comentario.

Mi idea original era tener más de una cadena de documentos en el sentido de:

def foo(): """docstring1: blah blah blah""" """docstring2: blah blah blah""" pass # Insert code here 

Luego habría algún código que podría usar para permitirme hacer referencia a cada una de estas cadenas de documentación. Entonces, ¿supongo que esto no es posible entonces?

No recomiendo tratar de hacer algo complicado con los docstrings. Lo mejor es mantener las cadenas de documentación simples y hacer algo más si desea que haya disponibles un montón de opciones de documentación diferentes.

Si realmente desea hacer lo que describió, le sugiero que use tags para delimitar las secciones dentro de las cadenas de documentación. Al igual que:

 def foo(bar, baz): """Function foo() * Summary: Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them. * Developers: When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests. * Testers: When you test foo, be sure to try negative values for baz. """ pass # code would go here 

Luego, puede dividir fácilmente su cadena en trozos, y cuando el usuario elige un elemento del menú, muestre solo los trozos apropiados.

 s = foo.__doc__ # s now refers to the docstring lst = s.split("\n* ") section = [section for section in lst if section.startswith("Developers")][0] print(section) # prints the "Developers" section 

De esta manera, cuando estés trabajando en el shell interactivo de Python, puedes decir “help (foo)” y verás todas las cadenas de documentación. Y, no estás cambiando el comportamiento fundamental de una parte básica de Python, que podría asustar a otras personas que intentan estudiar tu código.

También podría hacer algo aún más simple: solo haga un gran diccionario global de cadenas de documentos para diferentes propósitos, y actualícelo desde el código fuente para cada cosa nueva.

doc_developers = {} doc_testers = {}

 def foo(bar, baz): """Function foo() Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them." pass # code goes here doc_developers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests." doc_testers["foo"] = "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests." 

Lo más importante que no me gusta de esto es que, si cambia el nombre de la función foo, deberá cambiarlo en varios lugares: una vez en la def real y una por línea de actualización del diccionario. Pero en su mayoría podrías arreglar eso escribiendo una función:

 def doc_dict = {} # this will be a dict of dicts doc_dict["developers"] = {} doc_dict["testers"] = {} def doc_update(fn, d): name = fn.__name__ for key, value in d.items(): doc_dict[key][name] = value def foo(bar, baz): """Function foo() Function foo() handles all your foo-ish needs. You pass in a bar and a baz and it foos them." pass # code goes here d = { "developers": "When you change foo(), be sure you don't add any global variables, and don't forget to run the unit tests.", "testers": " When you test foo, be sure to try negative values for baz."} doc_update(foo, d) 

Probablemente hay una forma de convertir doc_update () en un decorador, pero ahora no tengo tiempo.

Desea considerar el uso de decoradores para hacer limpiamente lo que ~ unutbu propone para las funciones: agregar un campo separado para cada uno. Por ejemplo:

 def human_desc(description): def add_field(function): function.human_desc = description return function return add_field 

Así es como se human_desc en acción:

 @human_desc('This function eggfoobars its spam.') def eggfoobar(spam): "Apply egg, foo and bar to our spam metaclass object stuff." print spam 

Explicacion

Como explica el documento , ese bit de código es equivalente a lo siguiente:

 def eggfoobar(spam): "Apply egg, foo and bar to our spam metaclass object stuff." print spam eggfoobar = human_desc('This function eggfoobars its spam.')(eggfoobar) 

y human_desc('This function eggfoobars its spam.') devuelve la siguiente función:

 def add_field(function): function.human_desc = 'This function eggfoobars its spam.' return function 

Como puede ver, human_desc es una función que genera el decorador anterior para el valor de description que pasa como argumento. El decorador en sí es una función que acepta una función para ser decorada (modificada) y la devuelve decorada (en este caso, es decir, con la adición de ese bit de metadatos adicionales). En resumen esto es equivalente a:

 def eggfoobar(spam): "Apply egg, foo and bar to our spam metaclass object stuff." print spam eggfoobar.human_desc = 'This function eggfoobars its spam.' 

Sin embargo, la syntax es mucho más limpia y menos propensa a errores.

Obviamente, de cualquier manera, lo que obtienes es:

 >>> print eggfoobar.human_desc This function eggfoobars its spam. 

En lugar de usar una función, podría usar una clase con el usage y extra atributos extra definidos. Por ejemplo,

 class Foo(object): '''Here is the function's official docstring''' usage='All about the usage' extra='How another part works' def __call__(self): # Put the foo function code here pass foo=Foo() 

Lo llamaría como de costumbre: foo() , y puede obtener la cadena de documentación oficial, y alternar la cadena de documentación como esta:

 print foo.__doc__ print foo.usage print foo.extra 

También puedes adjuntar atributos adicionales a funciones simples (en lugar de usar una clase como lo hice anteriormente), pero creo que la syntax es un poco más fea:

 def foo(): pass foo.usage='Usage string' foo.extra='Extra string' 

Y, los módulos también son objetos. Pueden tener atributos adicionales con la misma facilidad:

Si define constantes de módulo

 USAGE='''blah blah''' EXTRA='''meow''' 

Luego cuando importas el módulo:

 import mymodule 

Puedes acceder a los documentos oficiales y alternativos con

 mymodule.__doc__ mymodule.USAGE mymodule.EXTRA 

Puede reemplazar el atributo __doc__ si desea tener más de una cadena de documentación posible, pero considere hacer la cadena de documentación inicial lo suficientemente flexible para todos los tipos.

El módulo es una colección de clases / funciones / módulos. Así que su cadena de documentos da la introducción sobre lo que contiene.

La cadena de documentación de la clase explica de qué se trata la clase y las cadenas de documentación de sus métodos indican qué métodos así lo hacen. Una clase sirve para un propósito y los métodos hacen una sola cosa, por lo que deberían tener una sola cadena de documentación.

Las funciones hacen una cosa, así que una doctrine debería ser suficiente para ellas.

No puedo ver qué propósito bastará con varias cadenas de documentación. Tal vez tu módulo sea grande. Divida en submódulos y en la cadena de documentación para el módulo mencione los submódulos.