Câu hỏi này dường như xuất hiện thường xuyên trên cả StackOverflow và các nơi khác, nhưng tôi không thể tìm thấy giải pháp hoàn toàn thỏa đáng ở bất cứ đâu.Python 3 - Phương pháp thừa kế docstring mà không phá vỡ trang trí hoặc vi phạm DRY
Dường như có hai loại giải pháp phổ biến. Người đầu tiên (từ ví dụ http://article.gmane.org/gmane.comp.python.general/630549) sử dụng một chức năng trang trí:
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__
Đây có lẽ là phương pháp đơn giản nhất, nhưng nó đòi hỏi lặp đi lặp lại tên lớp cha mẹ ít nhất một lần, và cũng có thể trở thành rất nhiều phức tạp hơn nếu docstring không thể được tìm thấy trong tổ tiên trực tiếp.
Cách tiếp cận thứ hai sử dụng một metaclass hoặc lớp trang trí (x Inheriting methods' docstrings in Python, Inherit a parent class docstring as __doc__ attribute, http://mail.python.org/pipermail/python-list/2011-June/606043.html) và trông như thế này:
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__
Tuy nhiên, với cách tiếp cận này docstring được chỉ đặt sau khi tạo lớp và do đó không có thể truy cập vào trang trí, vì vậy các công cụ sau sẽ không hoạt động:
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
Ý tưởng thú vị thứ ba đã được thảo luận trong Inherit docstrings in Python class inheritance. Ở đây, trình trang trí hàm thực sự kết thúc tốt đẹp phương thức và biến nó thành một bộ mô tả phương thức thay vì chỉ cập nhật chuỗi tài liệu của nó. Tuy nhiên, điều này có vẻ như sử dụng sledgehammer để crack một nut bởi vì nó biến phương thức thành một bộ mô tả phương thức (có thể có các hàm ý hiệu năng, mặc dù tôi không kiểm tra), và cũng không làm cho docstring có sẵn cho bất kỳ trang trí nào khác (và trong ví dụ trên sẽ thực sự khiến chúng sụp đổ vì bộ mô tả phương thức không có thuộc tính __name__
).
Có giải pháp nào tránh được tất cả các hạn chế ở trên, tức là không yêu cầu tôi lặp lại chính mình và gán ngay cho chuỗi tài liệu bằng trình trang trí không?
Tôi quan tâm đến một giải pháp cho Python 3.
Tôi thực hiện một chút thông minh hơn về điều này và một số ví dụ trên http://code.activestate.com/recipes/578587-inherit-method-docstrings-without-breaking-decorat/ – Nikratio