【问题标题】:How do I programmatically set the docstring?如何以编程方式设置文档字符串?
【发布时间】:2011-05-02 16:50:21
【问题描述】:

我有一个返回函数的包装函数。有没有办法以编程方式设置返回函数的文档字符串?如果我可以写信给__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__ 在我的情况下是可写的,但它不是。

我正在尝试自动为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

如果我创建这个类并尝试设置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

【问题讨论】:

  • 你为什么不写一个文档字符串?
  • @RaeKettler:因为如果你更新它,你必须始终记住手动更新所有其他包装函数中的所有其他副本

标签: python docstring


【解决方案1】:

instancemethod 从其__func__ 获取其文档字符串。改为更改 __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 docs:

用户定义的方法

用户定义的方法对象结合了一个类、一个类实例(或无)和任何可调用的 对象(通常是用户定义的函数)。

特殊的只读属性: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__。

【讨论】:

    【解决方案2】:

    我会将文档字符串传递给工厂函数并使用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')
    

    【讨论】:

      【解决方案3】:

      这是对type 类型的类的__doc__ 属性不能更改这一事实的补充。有趣的一点是,只要类是使用类型创建的,这才是正确的。只要您使用元类,您实际上就可以更改__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 !
      """
      

      【讨论】:

        【解决方案4】:

        只需使用装饰器。这是你的情况:

        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 dynamic help and autocomplete generation

        【讨论】:

          【解决方案5】:

          __doc__ 仅在您的对象为“类型”类型时不可写。

          在您的情况下,add_three 是一个函数,您可以将 __doc__ 设置为任何字符串。

          【讨论】:

            【解决方案6】:

            在您尝试自动生成 unittest.TestCase 子类的情况下,您可能需要更多的里程来覆盖他们的 shortDescription 方法。

            这是将底层文档字符串剥离到第一行的方法,如在正常的 unittest 输出中所见;覆盖它就足以让我们控制 TeamCity 等报告工具中显示的内容,这正是我们所需要的。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2016-08-14
              • 2010-09-26
              • 1970-01-01
              • 1970-01-01
              • 2017-01-25
              • 1970-01-01
              相关资源
              最近更新 更多