python3 - ¿Cómo configuro mediante programación la cadena de documentos?
python param doc (6)
Tengo una función de envoltorio que devuelve una función. ¿Hay una manera de establecer mediante programación la cadena de documentos de la función devuelta? Si pudiera escribir a __doc__
, haría lo siguiente:
def wrapper(a):
def add_something(b):
return a + b
add_something.__doc__ = ''Adds '' + str(a) + '' to `b`''
return add_something
Entonces podria hacer
>>> add_three = wrapper(3)
>>> add_three.__doc__
''Adds 3 to `b`
Sin embargo, dado que __doc__
es de solo lectura, no puedo hacer eso. ¿Cuál es la forma correcta?
Edit: Ok, quería mantener esto simple, pero por supuesto esto no es lo que realmente estoy tratando de hacer. Aunque en general __doc__
se puede escribir en mi caso no lo es.
Estoy tratando de crear testcases para unittest
automáticamente. Tengo una función de contenedor que crea un objeto de clase que es una subclase de unittest.TestCase
:
import unittest
def makeTestCase(filename, my_func):
class ATest(unittest.TestCase):
def testSomething(self):
# Running test in here with data in filename and function my_func
data = loadmat(filename)
result = my_func(data)
self.assertTrue(result > 0)
return ATest
Si creo esta clase e intento establecer la cadena de testSomething
de testSomething
, testSomething
un error:
>>> def my_func(): pass
>>> MyTest = makeTestCase(''some_filename'', my_func)
>>> MyTest.testSomething.__doc__ = ''This should be my docstring''
AttributeError: attribute ''__doc__'' of ''instancemethod'' objects is not writable
En el caso de que esté tratando de generar automáticamente subclases de Unittest.TestCase, es posible que tenga más millas sobrepasando su método de shortDescription .
Este es el método que elimina la cadena de documentos subyacente hasta la primera línea, como se ve en el resultado normal de unittest; anularlo fue suficiente para darnos control sobre lo que aparecía en herramientas de informes como TeamCity, que era lo que necesitábamos.
Esto es una adición al hecho de que el atributo __doc__
de las clases de tipo de type
no se puede cambiar. El punto interesante es que esto solo es cierto siempre y cuando la clase se cree utilizando type. Tan pronto como uses una metaclase, puedes cambiar __doc__
.
El ejemplo utiliza el módulo abc (AbstractBaseClass). Funciona utilizando una metaclase ABCMeta
especial ABCMeta
import abc
class MyNewClass(object):
__metaclass__ = abc.ABCMeta
MyClass.__doc__ = "Changing the docstring works !"
help(MyNewClass)
resultará en
"""
Help on class MyNewClass in module __main__:
class MyNewClass(__builtin__.object)
| Changing the docstring works !
"""
Supongo que esto debería ser un comentario, pero aún así estoy acumulando mis primeros 50 puntos ...
Pasaría la cadena de documentos a la función de fábrica y usaría el type
para construir manualmente la clase.
def make_testcase(filename, myfunc, docstring):
def test_something(self):
data = loadmat(filename)
result = myfunc(data)
self.assertTrue(result > 0)
clsdict = {''test_something'': test_something,
''__doc__'': docstring}
return type(''ATest'', (unittest.TestCase,), clsdict)
MyTest = makeTestCase(''some_filename'', my_func, ''This is a docstring'')
Sólo usa decoradores. Aquí está tu caso:
def add_doc(value):
def _doc(func):
func.__doc__ = value
return func
return _doc
import unittest
def makeTestCase(filename, my_func):
class ATest(unittest.TestCase):
@add_doc(''This should be my docstring'')
def testSomething(self):
# Running test in here with data in filename and function my_func
data = loadmat(filename)
result = my_func(data)
self.assertTrue(result > 0)
return ATest
def my_func(): pass
MyTest = makeTestCase(''some_filename'', my_func)
print MyTest.testSomething.__doc__
> ''This should be my docstring''
Este es un caso de uso similar: la ayuda dinámica de Python y la generación de autocompletado
Un método de instancemethod
obtiene su cadena de documentos de su __func__
. Cambiar la cadena de __func__
de __func__
en __func__
lugar. (El atributo __doc__
de las funciones se puede escribir.)
>>> class Foo(object):
... def bar(self):
... pass
...
>>> Foo.bar.__func__.__doc__ = "A super docstring"
>>> help(Foo.bar)
Help on method bar in module __main__:
bar(self) unbound __main__.Foo method
A super docstring
>>> foo = Foo()
>>> help(foo.bar)
Help on method bar in module __main__:
bar(self) method of __main__.Foo instance
A super docstring
De los 2.7 documentos :
Métodos definidos por el usuario
Un objeto de método definido por el usuario combina una clase, una instancia de clase (o Ninguna) y cualquier objeto llamable (normalmente una función definida por el usuario).
Atributos especiales de solo lectura: im_self es el objeto de instancia de clase, im_func es el objeto de función; im_class es la clase de im_self para métodos enlazados o la clase que solicitó el método para métodos no enlazados;
__doc__
es la documentación del método (igual queim_func.__doc__
);__name__
es el nombre del método (igual queim_func.__name__
);__module__
es el nombre del módulo en el que se definió el método, o Ninguno si no está disponible.Cambiado en la versión 2.2: im_self se usa para referirse a la clase que definió el método.
Modificado en la versión 2.6: para 3.0 compatibilidad hacia adelante, im_func también está disponible como
__func__
, y im_self como__self__
.
__doc__
no se puede escribir solo cuando su objeto es de tipo ''tipo''.
En su caso, add_three
es una función y solo puede establecer __doc__
a cualquier cadena.