在编写类

时间:2016-06-30 13:55:26

标签: python python-sphinx composition docstring

我有一个班级MyClass

class MyClass(object):
    def __init__(self):
        pass

    def my_function(self, x):
        # MyClass.my_function.__doc__ is not writable!
        # Otherwise, I could just set it here.
        Origin.func(self, x)

班级借鉴Origin

class Origin(object):    
    def func(obj, x):
        """This is a function
        """
        # do stuff
        pass

如何自动将文档字符串从Origin.func复制到MyClass.my_function,以便Sphinx Autodoc识别它?我怎么能用几个单词来扩展原始文档?

编辑:

Afaik,我不能在函数定义之后更改__doc__,因为Sphinx当时找不到它。或者如果确实如此," docfix"去吗?

1 个答案:

答案 0 :(得分:4)

我不清楚Sphinx究竟是如何工作的,但假设它从__doc__读取而不是解析源,则有许多选项。

考虑更简单的例子......

def add(x, y):
    return x + y

......几乎与......相同。

add = lambda x, y: x + y

在任何一种情况下,您都不能在其定义中引用符号add,因为此时未定义符号。您也不能引用符号function最终将引用的add对象,因为它尚未创建。

因此,您只能在定义符号后修改add.__doc__ ...

def add(x, y):
    return x + y
add.__doc__ = 'This is my docstring'

......但这可能比我们想要的更冗长。

另一个选择是利用Python装饰器语法...

这一事实
@my_decorator
def add(x, y):
    return x + y

......等同于......

def add(x, y):
    return x + y
add = my_decorator(add)

...也就是说,虽然在函数定义之前放置了,但在函数定义之后执行,所以可以引用装饰器函数体内的function对象。

返回一个可调用对象需要一个装饰器函数,但是由于我们不需要改变add函数的行为,我们可以只返回传递给装饰器的参数,所以给出装饰函数......

def set_fixed_docstring(func):
    func.__doc___ = 'This is my docstring'
    return func

...像......一样使用。

@set_fixed_docstring
def add(x, y):
    return x + y

......等同于......

def add(x, y):
    return x + y
add = set_fixed_docstring(add)

...或...

def add(x, y):
    return x + y
add.__doc__ = 'This is my docstring'
add = add

显然,修复的文档字符串在这里没什么用,所以我们需要参数化装饰器,这有点复杂。

在这个例子中,我们需要使用字符串参数来调用我们的装饰器函数,以返回一个可调用的对象,该对象将目标函数作为参数。

最常见的方法是在装饰器函数中定义另一个函数,这样内部函数可以引用外部函数中定义的符号。功能......

def set_docstring_to(docstring):
    def wrapper(func):
        func.__doc___ = docstring
        return func
    return wrapper

...像......一样使用。

@set_docstring_to('This is my docstring')
def add(x, y):
    return x + y

......等同于......

def add(x, y):
    return x + y
add = set_docstring_to('This is my docstring')(add)

...归结为与以前相同的代码......

def add(x, y):
    return x + y
add.__doc__ = 'This is my docstring'
add = add

把所有这些放在一起,如果你要使用像...这样的装饰者。

def copy_docstring_from(source):
    def wrapper(func):
        func.__doc__ = source.__doc__
        return func
    return wrapper

...那你就可以......

class Origin(object):
    def func(obj, x):
        """This is a function
        """
        # do stuff
        pass

class MyClass(object):
    def __init__(self):
        pass

    @copy_docstring_from(Origin.func)
    def my_function(self, x):
        # MyClass.my_function.__doc__ is not writable!
        # Otherwise, I could just set it here.
        Origin.func(self, x)

......应该以最少的代码量达到预期的效果。