这个问题似乎经常出现在StackOverflow和其他地方,但我没有找到一个完全满意的解决方案。在
似乎有两种常见的解决方案。第一个(例如http://article.gmane.org/gmane.comp.python.general/630549)使用函数修饰符:
class SuperClass:
def my_method(self):
'''Has a docstring'''
pass
class MyClass(SuperClass):
@copy_docstring_from(SuperClass)
def my_method(self):
pass
assert SuperClass.my_method.__doc__ == MyClass.my_method._doc__
这可能是最直接的方法,但它至少需要重复父类名一次,如果在直接祖先中找不到docstring,也会变得更加复杂。在
第二种方法使用元类或类修饰符(参见Inheriting methods' docstrings in Python,Inherit a parent class docstring as __doc__ attribute,http://mail.python.org/pipermail/python-list/2011-June/606043.html),如下所示:
^{pr2}$但是,使用这种方法,docstring只在类创建之后设置,因此装饰器无法访问,因此以下操作将不起作用:
def log_docstring(fn):
print('docstring for %s is %s' % (fn.__name__, fn.__doc__)
return fn
class MyClass(SuperClass, metaclass=MagicHappeningHere):
# or
#@frobnicate_docstrings
#class MyClass2(SuperClass):
@log_docstring
def method(self):
pass
第三个有趣的想法已经在Inherit docstrings in Python class inheritance中讨论过。这里,函数修饰符实际上包装了方法并将其转换为方法描述符,而不仅仅是更新其docstring。然而,这看起来像是在用大锤敲开一个螺母,因为它将方法转换为一个方法描述符(这可能也有性能影响,尽管我没有检查),并且也不会使docstring对任何其他装饰器可用(在上面的示例中,实际上会使它们崩溃,因为方法描述符没有__name__
属性)。在
是否有一个解决方案可以避免上述所有缺点,即不需要我重复自己的操作,并立即使用decorator分配docstring?在
我对Python3的解决方案感兴趣。在
请改用类修饰符:
其中
^{pr2}$inherit_docstrings()
定义为:演示:
这将在定义整个类之后设置docstring,而不必首先创建实例。在
如果您需要方法装饰器可以使用的docstring,那么不幸的是,您只能使用复制父类的decorator。在
这样做的原因是,在定义类主体时,不能反思超类将是什么。类定义期间的本地命名空间无权访问传递给类工厂的参数。在
您可以使用元类将基类添加到本地名称空间,然后使用修饰符再次拉出基类,但在我看来,这会变得丑陋、快速:
演示用法:
我认为可以通过注入一个知道类层次结构的decorator来使用元类
__prepare__
方法:印刷品:
^{pr2}$当然,这种方法还有一些其他问题: -一些分析工具(例如pyflakes)会抱怨使用(显然)未定义的
inherit_docstring
名称 -如果父类已经有一个不同的元类(例如ABCMeta
),那么它就不起作用了。在从python3.5开始,^{} 在继承树中搜索docstring。因此,如果您将子对象的docstring留空,它将从父对象检索它。这样就避免了代码重复的需要,像sphinx这样的自动代码生成器将做正确的事情。在
相关问题 更多 >
编程相关推荐