[英]How do I programmatically set the docstring?
I have a wrapper function that returns a function.我有一个返回函数的包装函数。 Is there a way to programmatically set the docstring of the returned function?有没有办法以编程方式设置返回函数的文档字符串? If I could write to __doc__
I'd do the following:如果我可以写信给__doc__
我会执行以下操作:
def wrapper(a):
def add_something(b):
return a + b
add_something.__doc__ = 'Adds ' + str(a) + ' to `b`'
return add_something
Then I could do然后我可以做
>>> add_three = wrapper(3)
>>> add_three.__doc__
'Adds 3 to `b`
However, since __doc__
is read-only, I can't do that.但是,由于__doc__
是只读的,我不能这样做。 What's the correct way?正确的方法是什么?
Edit: Ok, I wanted to keep this simple, but of course this is not what I'm actually trying to do.编辑:好的,我想保持这个简单,但当然这不是我真正想要做的。 Even though in general __doc__
is writeable in my case it isn't.尽管通常__doc__
在我的情况下是可写的,但它不是。
I am trying to create testcases for unittest
automatically.我正在尝试自动为unittest
创建测试用例。 I have a wrapper function that creates a class object that is a subclass of unittest.TestCase
:我有一个包装函数,它创建一个类对象,它是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
If I create this class and try to set the docstring of testSomething
I get an error:如果我创建这个类并尝试设置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
An instancemethod
gets its docstring from its __func__
.一个instancemethod
从它的__func__
获取它的文档字符串。 Change the docstring of __func__
instead.改为更改__func__
的文档字符串。 (The __doc__
attribute of functions are writeable.) (函数的__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
User-defined methods用户定义的方法
A user-defined method object combines a class, a class instance (or None) and any callable object (normally a user-defined function).用户定义的方法对象组合了一个类、一个类实例(或 None)和任何可调用对象(通常是一个用户定义的函数)。
Special read-only attributes: im_self is the class instance object, im_func is the function object;特殊的只读属性:im_self 是类实例对象,im_func 是函数对象; im_class is the class of im_self for bound methods or the class that asked for the method for unbound methods; im_class 是绑定方法的 im_self 类或未绑定方法请求方法的类;
__doc__
is the method's documentation (same asim_func.__doc__
);__doc__
是方法的文档(与im_func.__doc__
相同);__name__
is the method name (same asim_func.__name__
);__name__
是方法名称(与im_func.__name__
相同);__module__
is the name of the module the method was defined in, or None if unavailable.__module__
是定义方法的模块的名称,如果不可用则为 None 。Changed in version 2.2: im_self used to refer to the class that defined the method.在 2.2 版更改: im_self 用于引用定义方法的类。
Changed in version 2.6: For 3.0 forward-compatibility, im_func is also available as
__func__
, and im_self as__self__
.在 2.6 版更改:对于 3.0 向前兼容性, im_func 也可用作__func__
, im_self 可用作__self__
。
I would pass the docstring into the factory function and use type
to manually construct the class.我会将文档字符串传递给工厂函数并使用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')
This is an addition to the fact that the __doc__
attribute of classes of type type
cannot be changed.这是对 type type
的类的__doc__
属性无法更改这一事实的补充。 The interesting point is that this is only true as long as the class is created using type.有趣的一点是,这仅在类是使用类型创建的情况下才成立。 As soon as you use a metaclass you can actually just change __doc__
.只要您使用元类,您实际上就可以更改__doc__
。
The example uses the abc (AbstractBaseClass) module.该示例使用 abc (AbstractBaseClass) 模块。 It works using a special ABCMeta
metaclass它使用特殊的ABCMeta
元类工作
import abc
class MyNewClass(object):
__metaclass__ = abc.ABCMeta
MyClass.__doc__ = "Changing the docstring works !"
help(MyNewClass)
will result in会导致
"""
Help on class MyNewClass in module __main__:
class MyNewClass(__builtin__.object)
| Changing the docstring works !
"""
Just use decorators.只需使用装饰器。 Here's your case:这是你的情况:
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'
Here's a similar use case: Python dynamic help and autocomplete generation这是一个类似的用例: Python dynamic help and autocomplete generation
__doc__
is not writable only when your object is of type 'type'. __doc__
仅当您的对象属于“类型”类型时才可写。
In your case, add_three
is a function and you can just set __doc__
to any string.在您的情况下, add_three
是一个函数,您可以将__doc__
设置为任何字符串。
In the case where you're trying to automatically generate unittest.TestCase subclasses, you may have more mileage overriding their shortDescription method.在您尝试自动生成 unittest.TestCase 子类的情况下,您可能有更多的里程覆盖他们的shortDescription方法。
This is the method that strips the underlying docstring down to the first line, as seen in normal unittest output;这是将底层文档字符串剥离到第一行的方法,如正常的单元测试输出所示; overriding it was enough to give us control over what showed up in reporting tools like TeamCity, which was what we needed.覆盖它足以让我们控制在 TeamCity 等报告工具中显示的内容,这正是我们所需要的。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.