2010-10-30 52 views
38

我有一個包裝函數,返回一個函數。有沒有辦法以編程方式設置返回的函數的文檔字符串?如果我能寫__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 
+1

你爲什麼不只需寫一個文檔字符串? – 2010-10-30 03:02:20

+5

@RaeKettler:因爲如果你更新它,你必須記得手動更新所有其他包裝函數中的所有其他副本 – endolith 2012-07-11 16:11:42

回答

13

我會將文檔字符串傳遞給工廠函數,並使用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') 
4

__doc__只有當你的對象是'type'類型時纔可寫。

在你的情況下,add_three是一個函數,你可以設置__doc__任何字符串。

41

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

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).

Special read-only attributes: im_self is the class instance object, im_func is the function object; im_class is the class of im_self for bound methods or the class that asked for the method for unbound methods; __doc__ is the method’s documentation (same as im_func.__doc__);__name__ is the method name (same as im_func.__name__); __module__ is the name of the module the method was defined in, or None if unavailable.

Changed in version 2.2: im_self used to refer to the class that defined the method.

Changed in version 2.6: For 3.0 forward-compatibility, im_func is also available as __func__ , and im_self as __self__ .

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

0

在你想自動生成的子類unittest.TestCase生成的情況下,你可能有更多的里程重寫他們的shortDescription方法。

這是將底層docstring剝離到第一行的方法,如在普通單元測試輸出中所見;重寫它足以讓我們控制像TeamCity這樣的報告工具,這正是我們所需要的。

5

這是對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 ! 
""" 

我想這應該是一個評論,但仍在收集我的第一個50分...

相關問題