Fre*_*Foo 51 python oop inheritance docstring template-method-pattern
我有一个带有文档字符串的OO层次结构,它需要与代码本身一样多的维护.例如,
class Swallow(object):
def airspeed(self):
"""Returns the airspeed (unladen)"""
raise NotImplementedError
class AfricanSwallow(Swallow):
def airspeed(self):
# whatever
Run Code Online (Sandbox Code Playgroud)
现在,问题是AfricanSwallow.airspeed
不继承超类方法的docstring.我知道我可以使用模板方法模式保留文档字符串,即
class Swallow(object):
def airspeed(self):
"""Returns the airspeed (unladen)"""
return self._ask_arthur()
Run Code Online (Sandbox Code Playgroud)
并_ask_arthur
在每个子类中实现.但是,我想知道是否还有另一种方法可以继承docstrings,也许还有一些我尚未发现的装饰器?
unu*_*tbu 23
这是Paul McGuire的DocStringInheritor元类的变体.
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)
Run Code Online (Sandbox Code Playgroud)
Ray*_*ger 22
在类装饰器样式中编写一个函数来为您进行复制.在Python2.5中,您可以在创建类之后直接应用它.在以后的版本中,您可以使用@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__
Run Code Online (Sandbox Code Playgroud)
在较新的Python版本中,最后一部分更加简单和美观:
@fix_docs
class Dog(Animal):
def walk(self):
pass
Run Code Online (Sandbox Code Playgroud)
这是一种Pythonic技术,与标准库中现有工具的设计完全匹配.例如,functools.total_ordering类装饰器向类添加缺少的丰富比较方法.另一个例子是,functools.wraps装饰器将元数据从一个函数复制到另一个函数.
Rya*_*ski 13
FYI刚才有人关注这个主题:从Python 3.5开始,inspect.getdoc会自动从继承层次结构中检索文档字符串.
因此,上面的回答对Python 2很有用,或者如果你想在合并父母和孩子的文档字符串时更有创意.
我还为docstring继承创建了一些轻量级工具.这些支持一些不错的默认文档字符串样式(numpy,google,reST)开箱即用.您也可以轻松使用自己的文档字符串样式
归档时间: |
|
查看次数: |
6159 次 |
最近记录: |