2010-10-30 44 views
38

Tôi có hàm bao hàm trả về hàm. Có cách nào để lập trình docstring của hàm trả về không? Nếu tôi có thể viết thư cho __doc__ Tôi muốn làm như sau:Làm cách nào để đặt docstring theo chương trình?

def wrapper(a): 
    def add_something(b): 
     return a + b 
    add_something.__doc__ = 'Adds ' + str(a) + ' to `b`' 
    return add_something 

Sau đó, tôi có thể làm

>>> add_three = wrapper(3) 
>>> add_three.__doc__ 
'Adds 3 to `b` 

Tuy nhiên, vì __doc__ là read-only, tôi không thể làm điều đó. Cách chính xác là gì?


Chỉnh sửa: Ok, tôi muốn giữ điều này đơn giản, nhưng tất nhiên đây không phải là những gì tôi thực sự đang cố gắng thực hiện. Mặc dù nói chung, __doc__ có thể ghi được trong trường hợp của tôi.

Tôi đang cố gắng tạo testcases cho unittest tự động. Tôi có một chức năng bao bọc tạo ra một đối tượng lớp đó là một lớp con của 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 

Nếu tôi tạo lớp này và cố gắng thiết lập các docstring của testSomething tôi nhận được một lỗi:

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

Tại sao bạn không chỉ cần viết một docstring? –

+5

@RaeKettler: Bởi vì sau đó nếu bạn cập nhật nó, bạn phải luôn luôn nhớ cập nhật thủ công tất cả các bản sao khác trong tất cả các hàm bao bọc khác – endolith

Trả lời

13

Tôi sẽ chuyển chuỗi tài liệu vào chức năng của nhà máy và sử dụng type để xây dựng lớp học theo cách thủ công.

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__ không thể ghi khi đối tượng của bạn thuộc loại 'type'.

Trong trường hợp của bạn, add_three là một hàm và bạn chỉ có thể đặt __doc__ thành chuỗi bất kỳ.

41

An instancemethod nhận chuỗi tài liệu từ __func__. Thay vào đó, hãy thay đổi chuỗi tài liệu của __func__. (Các __doc__ thuộc tính của chức năng này là rất có khả năng ghi.)

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

Từ 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

Chỉ cần sử dụng trang trí. Đây là trường hợp của bạn:

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' 

Dưới đây là một trường hợp sử dụng tương tự: Python dynamic help and autocomplete generation

0

Trong trường hợp bạn đang cố gắng để tự động tạo các lớp con unittest.TestCase, bạn có thể có số dặm hơn trọng phương pháp shortDescription của họ.

Đây là phương pháp tách chuỗi tài liệu cơ bản xuống dòng đầu tiên, như được thấy trong đầu ra không bình thường thông thường; ghi đè nó là đủ để cho chúng tôi kiểm soát những gì xuất hiện trong các công cụ báo cáo như TeamCity, đó là những gì chúng tôi cần.

5

Đây là sự bổ sung cho thực tế là thuộc tính __doc__ của các loại kiểu type không thể thay đổi. Điểm thú vị là điều này chỉ đúng khi lớp được tạo ra bằng cách sử dụng kiểu. Ngay sau khi bạn sử dụng một metaclass bạn thực sự có thể chỉ cần thay đổi __doc__.

Ví dụ sử dụng mô-đun abc (AbstractBaseClass). Nó hoạt động bằng cách sử dụng ABCMeta metaclass đặc biệt

import abc 

class MyNewClass(object): 
    __metaclass__ = abc.ABCMeta 

MyClass.__doc__ = "Changing the docstring works !" 

help(MyNewClass) 

sẽ dẫn đến

""" 
Help on class MyNewClass in module __main__: 

class MyNewClass(__builtin__.object) 
| Changing the docstring works ! 
""" 

Tôi giả định này phải là một bình luận, nhưng vẫn thu thập 50 của tôi điểm đầu tiên ...

Các vấn đề liên quan