python oop 继承_oop-在Python中继承方法的文档字符串
oop-在Python中繼承方法的文檔字符串
我有一個帶有文檔字符串的OO層次結構,它需要與代碼本身一樣多的維護。 例如。,
class Swallow(object):
def airspeed(self):
"""Returns the airspeed (unladen)"""
raise NotImplementedError
class AfricanSwallow(Swallow):
def airspeed(self):
# whatever
現(xiàn)在,問題是_ask_arthur不繼承超類方法的文檔字符串。 我知道我可以使用模板方法模式來保留文檔字符串,即
class Swallow(object):
def airspeed(self):
"""Returns the airspeed (unladen)"""
return self._ask_arthur()
并在每個子類中實現(xiàn)_ask_arthur。 但是,我想知道是否還有另一種方法來繼承文檔字符串,也許是我還沒有發(fā)現(xiàn)的裝飾器?
5個解決方案
23 votes
這是Paul McGuire的DocStringInheritor元類的變體。
如果子成員的文檔字符串繼承,則它會繼承父成員的文檔字符串docstring為空。
如果子類docstring為,它將繼承父類docstring。空的。
它可以從以下任何類繼承文檔字符串任何基類的MRO,就像常規(guī)屬性繼承一樣。
與類裝飾器不同,元類是繼承的,因此您只需要在某些頂級基類中設置一次元類,并且docstring繼承將在整個OOP層次結構中發(fā)生。
import unittest
import sys
class DocStringInheritor(type):
"""
A variation on
http://groups.google.com/group/comp.lang.python/msg/26f7b4fcb4d66c95
by Paul McGuire
"""
def __new__(meta, name, bases, clsdict):
if not('__doc__' in clsdict and clsdict['__doc__']):
for mro_cls in (mro_cls for base in bases for mro_cls in base.mro()):
doc=mro_cls.__doc__
if doc:
clsdict['__doc__']=doc
break
for attr, attribute in clsdict.items():
if not attribute.__doc__:
for mro_cls in (mro_cls for base in bases for mro_cls in base.mro()
if hasattr(mro_cls, attr)):
doc=getattr(getattr(mro_cls,attr),'__doc__')
if doc:
if isinstance(attribute, property):
clsdict[attr] = property(attribute.fget, attribute.fset,
attribute.fdel, doc)
else:
attribute.__doc__ = doc
break
return type.__new__(meta, name, bases, clsdict)
class Test(unittest.TestCase):
def test_null(self):
class Foo(object):
def frobnicate(self): pass
class Bar(Foo, metaclass=DocStringInheritor):
pass
self.assertEqual(Bar.__doc__, object.__doc__)
self.assertEqual(Bar().__doc__, object.__doc__)
self.assertEqual(Bar.frobnicate.__doc__, None)
def test_inherit_from_parent(self):
class Foo(object):
'Foo'
def frobnicate(self):
'Frobnicate this gonk.'
class Bar(Foo, metaclass=DocStringInheritor):
pass
self.assertEqual(Foo.__doc__, 'Foo')
self.assertEqual(Foo().__doc__, 'Foo')
self.assertEqual(Bar.__doc__, 'Foo')
self.assertEqual(Bar().__doc__, 'Foo')
self.assertEqual(Bar.frobnicate.__doc__, 'Frobnicate this gonk.')
def test_inherit_from_mro(self):
class Foo(object):
'Foo'
def frobnicate(self):
'Frobnicate this gonk.'
class Bar(Foo):
pass
class Baz(Bar, metaclass=DocStringInheritor):
pass
self.assertEqual(Baz.__doc__, 'Foo')
self.assertEqual(Baz().__doc__, 'Foo')
self.assertEqual(Baz.frobnicate.__doc__, 'Frobnicate this gonk.')
def test_inherit_metaclass_(self):
class Foo(object):
'Foo'
def frobnicate(self):
'Frobnicate this gonk.'
class Bar(Foo, metaclass=DocStringInheritor):
pass
class Baz(Bar):
pass
self.assertEqual(Baz.__doc__, 'Foo')
self.assertEqual(Baz().__doc__, 'Foo')
self.assertEqual(Baz.frobnicate.__doc__, 'Frobnicate this gonk.')
def test_property(self):
class Foo(object):
@property
def frobnicate(self):
'Frobnicate this gonk.'
class Bar(Foo, metaclass=DocStringInheritor):
@property
def frobnicate(self): pass
self.assertEqual(Bar.frobnicate.__doc__, 'Frobnicate this gonk.')
if __name__ == '__main__':
sys.argv.insert(1, '--verbose')
unittest.main(argv=sys.argv)
unutbu answered 2020-01-27T02:02:29Z
22 votes
以類裝飾器風格編寫一個函數(shù)來為您執(zhí)行復制。 在Python2.5中,您可以在創(chuàng)建類后直接應用它。 在更高版本中,您可以使用@decorator表示法。
這是如何做到的第一步:
import types
def fix_docs(cls):
for name, func in vars(cls).items():
if isinstance(func, types.FunctionType) and not func.__doc__:
print func, 'needs doc'
for parent in cls.__bases__:
parfunc = getattr(parent, name, None)
if parfunc and getattr(parfunc, '__doc__', None):
func.__doc__ = parfunc.__doc__
break
return cls
class Animal(object):
def walk(self):
'Walk like a duck'
class Dog(Animal):
def walk(self):
pass
Dog = fix_docs(Dog)
print Dog.walk.__doc__
在較新的Python版本中,最后一部分更加簡單美觀:
@fix_docs
class Dog(Animal):
def walk(self):
pass
這是一項Pythonic技術,與標準庫中現(xiàn)有工具的設計完全匹配。 例如,functools.total_ordering類裝飾器向類添加缺少的豐富比較方法。 再舉一個例子,functools.wraps裝飾器將元數(shù)據(jù)從一個函數(shù)復制到另一個函數(shù)。
Raymond Hettinger answered 2020-01-27T02:01:51Z
13 votes
僅供參考的FYY I人員:在Python 3.5上,inspection.getdoc自動從繼承層次結構中檢索文檔字符串。
因此,上面的響應對于Python 2很有用,或者如果您想通過合并父母和孩子的文檔字符串來變得更有創(chuàng)造力,那么它們很有用。
我還創(chuàng)建了一些用于文檔字符串繼承的輕量級工具。 這些支持開箱即用的一些不錯的默認文檔字符串樣式(numpy,google,reST)。 您也可以輕松使用自己的文檔字符串樣式
Ryan Soklaski answered 2020-01-27T02:02:59Z
4 votes
以下適應還處理屬性和mixin類。 我還遇到了不得不使用func.__func__(用于“實例方法”)的情況,但我不確定為什么其他解決方案不能解決這個問題。
def inherit_docs(cls):
for name in dir(cls):
func = getattr(cls, name)
if func.__doc__:
continue
for parent in cls.mro()[1:]:
if not hasattr(parent, name):
continue
doc = getattr(parent, name).__doc__
if not doc:
continue
try:
# __doc__'s of properties are read-only.
# The work-around below wraps the property into a new property.
if isinstance(func, property):
# We don't want to introduce new properties, therefore check
# if cls owns it or search where it's coming from.
# With that approach (using dir(cls) instead of var(cls))
# we also handle the mix-in class case.
wrapped = property(func.fget, func.fset, func.fdel, doc)
clss = filter(lambda c: name in vars(c).keys() and not getattr(c, name).__doc__, cls.mro())
setattr(clss[0], name, wrapped)
else:
try:
func = func.__func__ # for instancemethod's
except:
pass
func.__doc__ = doc
except: # some __doc__'s are not writable
pass
break
return cls
letmaik answered 2020-01-27T02:03:19Z
0 votes
def fix_docs(cls):
""" copies docstrings of derived attributes (methods, properties, attrs) from parent classes."""
public_undocumented_members = {name: func for name, func in vars(cls).items()
if not name.startswith('_') and not func.__doc__}
for name, func in public_undocumented_members.iteritems():
for parent in cls.mro()[1:]:
parfunc = getattr(parent, name, None)
if parfunc and getattr(parfunc, '__doc__', None):
if isinstance(func, property):
# copy property, since its doc attribute is read-only
new_prop = property(fget=func.fget, fset=func.fset,
fdel=func.fdel, doc=parfunc.__doc__)
cls.func = new_prop
else:
func.__doc__ = parfunc.__doc__
break
return cls
marscher answered 2020-01-27T02:03:35Z
總結
以上是生活随笔為你收集整理的python oop 继承_oop-在Python中继承方法的文档字符串的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 派对屋3000效果器怎样调试_怎样测试自
- 下一篇: 小鹤双拼记忆口诀_选择双拼之自然码