根据类属性,通过装饰器修改类方法的文档字符串

2024-05-21 07:24:25 发布

您现在位置:Python中文网/ 问答频道 /正文

让我们从这个开始:

class Example(object):

    change_docstring = True

    @add_to_docstring(" (additional content!)")
    def example_method(self):
        """Example docstring."""
        pass

我要做的是允许@add_to_docstring装饰器仅在change_docstring属性是True时,才允许@add_to_docstring装饰器将其参数字符串附加到方法的docstring中。我不想把其他东西交给装饰工。在

这个解决方案是可行的,但它并不是我想要的。在

^{pr2}$

让我解释一下。在

上述解决方案仅在执行example_method时更改docstring。加载类、方法等时,docstring不会更改。在

>>> Example.example_method.__doc__
"wrapper docstring."
>>>
>>> Example().example_method()
>>> Example.example_method.__doc__
"Example docstring. (additional content!)"

我希望上面命令的输出是:

>>> Example.example_method.__doc__
"Example docstring. (additional content!)"

再说一次,我不想把别的东西交给装修工。在

更新

为了进一步说明,这是为了允许装饰者更改方法的docstring,并将该更改反映在Sphinx生成的文档中。Sphinx加载所有内容并收集docstring,但它不执行任何其他操作。在

基于所选的解决方案,我在decorators模块中添加了一个module变量,并公开了一个在decorators中禁用docstring更改特性的方法。为了全面禁用该功能,我在Sphinxconf.py文件中调用了disable函数,如下所示:

# import the decorators module
from some_modules import decorators
# disable the docstring change feature
decorators.disable_docstring_change()

然后decorator可以在项目中的任何方法上使用,并且docstring更改将被启用或禁用。在


Tags: to方法decoratorsadddocexample装饰content
2条回答

装饰并标记方法

对于函数签名,我们不需要关心太多,不管它是绑定的还是未绑定的——我们只需在函数对象上添加一个带有附加文本的属性。在

def add_to_docstring(text):
    def func(f):
        f.__add_to_docstring = text
        return f
    return func

修饰类以表明我们希望标记的方法得到遵守

通过使用一个类修饰符,我们可以指示我们希望使用标记的方法并更改docstring。我们扫描可调用的对象,检查它们是否是包含要添加到docstring中的修饰对象,并在返回具有不同函数docstring的新类型之前进行适当的更改。在

^{pr2}$

把它们放在一起

^{3}$

检查Example.example.__doc__我们得到-' something here (cabbage!)',如果删除@change_docstrings类修饰符,则不会有任何更改。在

请注意,这会将change_docstrings移出类,并转移到您是否修饰的位置,但是它允许这样的构造:

unchanged_docstrings = Example
changed_docstrings = change_docstrings(Example)

正如Martijn Pieter's answer到“从类定义中的列表理解访问类变量”中所述,如果您在类的新范围内,则不能访问类属性。这个答案主要集中在类范围内的理解和生成器表达式上,但同样适用于普通函数,包括decorator。在

一个简单的方法是使change_docstring成为一个全局的,并在类之前定义它,这样就可以很容易地逐个类对其进行设置。另一个选择是将它作为装饰者的一个参数,但您说过您不希望这样做。下面是一个可以同时在python2&3上运行的简短演示。在

def add_to_docstring(text):
    def decorator(original_method):
        def wrapper(self):
            return original_method(self)
        wrapper.__doc__ = original_method.__doc__
        if change_docstring:
            wrapper.__doc__ += text
        return wrapper
    return decorator

change_docstring = True
class Example(object):
    @add_to_docstring(" (additional content!)")
    def example_method(self):
        """Example docstring."""
        pass

change_docstring = False
class Other(object):
    @add_to_docstring(" (more content!)")
    def example_method(self):
        """Other docstring."""
        pass

print(Example.example_method.__doc__)
print(Other.example_method.__doc__)

输出

^{pr2}$

相关问题 更多 >