让我们从这开始:
class Example(object):
change_docstring = True
@add_to_docstring(" (additional content!)")
def example_method(self):
"""Example docstring."""
pass
我想要做的是允许@add_to_docstring
装饰器将其参数字符串附加到 方法的docstring中{{1} } attribute是change_docstring
。我不想要将任何其他内容传递给装饰器。
这个解决方案有效,但它并不是我想要的。
True
让我解释一下。
上述解决方案仅在执行def add_to_docstring(text):
def decorator(original_method):
def wrapper(self):
"""wrapper docstring."""
wrapper.__doc__ = original_method.__doc__
if self.change_docstring:
wrapper.__doc__ += text
return original_method(self)
return wrapper
return decorator
时更改文档字符串。加载类,方法等时,docstring不会改变。
example_method
这就是我想要的上述命令的输出:
>>> Example.example_method.__doc__
"wrapper docstring."
>>>
>>> Example().example_method()
>>> Example.example_method.__doc__
"Example docstring. (additional content!)"
同样,我不想将任何其他内容传递给装饰器。
为了进一步说明,这是为了允许装饰器更改方法的文档字符串,并使该更改反映在Sphinx生成的文档中。 Sphinx加载所有内容并收集文档字符串,但它不再做任何事情。
根据选定的解决方案,我在decorators模块中添加了一个模块变量,并公开了一个方法来禁用装饰器中的文档字符串更改功能。为了普遍禁用该功能,我在我的Sphinx >>> Example.example_method.__doc__
"Example docstring. (additional content!)"
文件中调用了禁用功能,如下所示:
conf.py
然后可以在项目中的任何方法上使用装饰器,并且可以启用或禁用文档字符串更改。
答案 0 :(得分:1)
如Martijn Pieter's answer至&#34中所述;从类定义中的列表理解中访问类变量"如果您在班级的新范围内,则无法访问类属性。该答案主要关注类范围中的理解和生成器表达式,但这同样适用于普通函数,包括装饰器。
解决这个问题的一个简单方法是使change_docstring
成为全局变量,并在类之前定义它,以便您可以在逐个类的基础上轻松设置它。另一个选择是让它成为装饰者的一个参数,但是你说你不喜欢这样做。这是一个适用于Python 2和DSP的简短演示。 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__)
<强>输出强>
Example docstring. (additional content!)
Other docstring.
答案 1 :(得分:1)
装饰并标记方法
我们不需要在这里关心函数签名,无论它是绑定还是未绑定 - 我们只是将一个带有附加文本的属性放在函数对象上。无论它是什么。
def add_to_docstring(text):
def func(f):
f.__add_to_docstring = text
return f
return func
装饰该类以表明我们希望标记的方法得到尊重
通过使用类装饰器,我们可以表明我们希望遵守标记方法并更改文档字符串。我们扫描可调用对象,检查它们是否是包含要添加到docstring的内容的装饰对象,并在返回具有不同函数docstrings的新类型之前进行适当的更改。
def change_docstrings(cls):
for obj in vars(cls).values():
if callable(obj) and hasattr(obj, '__add_to_docstring'):
obj.__doc__ = (obj.__doc__ or '') + obj.__add_to_docstring
del obj.__add_to_docstring
return cls
将它们放在一起
@change_docstrings
class Example:
@add_to_docstring('(cabbage!)')
def example(self):
""" something here """
pass
检查Example.example.__doc__
我们得到 - ' something here (cabbage!)'
,如果您删除@change_docstrings
类装饰器,则不会有任何更改。
请注意,这会将change_docstrings
移出类,无论您是否装饰,但是,它允许构造如下:
unchanged_docstrings = Example
changed_docstrings = change_docstrings(Example)