這個問題似乎定期出現在StackOverflow和其他地方,但我無法在任何地方找到完全令人滿意的解決方案。Python 3 - 不破壞裝飾器或違反DRY的方法docstring繼承
似乎有兩種常見的解決方案。第一個(例如從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__
這可能是最直接的方法,但它需要重複父類的名字至少一次,也成爲如果文檔字符串複雜得多在直接的祖先中找不到。
第二種方法使用元類或類裝飾(參見Inheriting methods' docstrings in Python,Inherit a parent class docstring as __doc__ attribute,http://mail.python.org/pipermail/python-list/2011-June/606043.html)和看起來像這樣:
class MyClass1(SuperClass, metaclass=MagicHappeningHere):
def method(self):
pass
# or
@frobnicate_docstrings
class MyClass2(SuperClass):
def method(self):
pass
assert SuperClass.my_method.__doc__ == MyClass1.my_method._doc__
assert SuperClass.my_method.__doc__ == MyClass2.my_method._doc__
然而,這種方法的文檔字符串類創建之後,才設置,因此不訪問裝飾,所以下面將不工作:
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了討論。這裏,函數裝飾器實際上包裝了方法並將其轉換爲方法描述符,而不僅僅是更新其文檔字符串。然而,這看起來像使用大錘來破解一個堅果,因爲它將方法轉變爲一個方法描述符(雖然我沒有檢查,但也可能會有性能影響),也不會使任何其他裝飾器可用的文檔字符串(和在上面的例子中實際上會使它們崩潰,因爲方法描述符沒有__name__
屬性)。
是否有避免上述缺點的解決方案,即不需要我重複自己並使用裝飾器立即分配文檔字符串?
我感興趣的Python 3
我在http://code.activestate.com/recipes/578587-inherit-method-docstrings-without-breaking-decorat/上放了一個稍微更巧妙的實現方法 – Nikratio