Как программно установить docstring?
У меня есть функция-обертка, которая возвращает функцию. Есть ли способ программно установить docstring возвращаемой функции? Если бы я мог написать __doc__
, я бы сделал следующее:
def wrapper(a):
def add_something(b):
return a + b
add_something.__doc__ = 'Adds ' + str(a) + ' to `b`'
return add_something
Тогда я мог бы сделать
>>> add_three = wrapper(3)
>>> add_three.__doc__
'Adds 3 to `b`
Однако, поскольку __doc__
доступен только для чтения, я не могу этого сделать. Каков правильный путь?
Изменить: Хорошо, я хотел сохранить это просто, но, конечно, это не то, что я на самом деле пытаюсь сделать. Хотя вообще __doc__
можно записать в моем случае, это не так.
Я пытаюсь создать testcases для unittest
автоматически. У меня есть оберточная функция, которая создает объект класса, который является подклассом 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
Если я создам этот класс и попытаюсь установить docstring из testSomething
, я получаю сообщение об ошибке:
>>> 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
Ответы
Ответ 1
Я передал бы docstring в функцию factory и использовал type
для ручной сборки класса.
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')
Ответ 2
An instancemethod
получает свою docstring из __func__
. Вместо этого измените docstring __func__
. (Атрибут __doc__
функций записывается.)
>>> 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
Из 2.7 документов:
Пользовательские методы
Пользовательский объект метода объединяет класс, экземпляр класса (или None) и любые вызываемые object (обычно определяемая пользователем функция).
Специальные атрибуты только для чтения: im_self - это объект экземпляра класса, im_func - это функция объект; im_class - это класс im_self для связанных методов или класс, который запрашивал метод для несвязанных методов; __doc__
- это документация методов (такая же, как im_func.__doc__
); __name__
- это имя метода (такое же, как im_func.__name__
); __module__
- это имя модуля, в котором был определен метод, или None, если он недоступен.
Изменено в версии 2.2: im_self используется для обозначения класса, который определил метод.
Изменено в версии 2.6: для версии 3.0 с поддержкой прямой совместимости im_func также доступен как __func__
, и im_self как __self__
.
Ответ 3
Просто используйте декораторы. Вот ваш случай:
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'
Здесь аналогичный прецедент: Динамическая справка Python и генерация автозаполнения
Ответ 4
__doc__
недоступен для записи только тогда, когда ваш объект имеет тип "тип".
В вашем случае add_three
является функцией, и вы можете просто установить __doc__
для любой строки.
Ответ 5
Это дополнение к тому, что атрибут __doc__
классов типа type
не может быть изменен. Интересным моментом является то, что это верно только в том случае, если класс создается с использованием типа. Как только вы используете метакласс, вы можете просто изменить __doc__
.
В этом примере используется модуль abc (AbstractBaseClass). Он работает с использованием специального метакласса ABCMeta
import abc
class MyNewClass(object):
__metaclass__ = abc.ABCMeta
MyClass.__doc__ = "Changing the docstring works !"
help(MyNewClass)
приведет к
"""
Help on class MyNewClass in module __main__:
class MyNewClass(__builtin__.object)
| Changing the docstring works !
"""
Я предполагаю, что это должен быть комментарий, но все же собирать мои первые 50 баллов...
Ответ 6
В случае, когда вы пытаетесь автоматически генерировать подклассы unittest.TestCase, у вас может быть больше пробега, переопределяющего метод shortDescription.
Это метод, который разбивает базовую docstring на первую строку, как видно из обычного unittest output; переопределить это было достаточно, чтобы дать нам контроль над тем, что появилось в средствах отчетности, таких как TeamCity, что было нам нужно.