假设我有两个类(A
& B
),其中第二个类派生自第一个类。此外,我通过在B中编写新实现来隐藏A中实现的一些属性。但是,我为A编写的文档字符串仍然适用于B而我懒惰 - 我不想复制粘贴一切。
请注意,这里的一个关键问题是我的目标是属性,对于类方法一般有解决方案。
在代码中,类的最小示例可能如下所示:
In [1]: class A(object):
...: @property
...: def a(self):
...: "The a:ness of it"
...: return True
...:
In [2]: class B(A):
...: @property
...: def a(self):
...: return False
...:
我基本上想要的是有办法实现以下目标:
In [8]: B.a.__doc__
Out[8]: 'The a:ness of it'
实际上B.a的文档字符串是空的,写B.a.__doc__
是不可能的,因为它会引发TypeError
。
据我所知,以下是一个解决方案:
from inspect import getmro
def inheritDocFromA(f):
"""This decorator will copy the docstring from ``A`` for the
matching function ``f`` if such exists and no docstring has been added
manually.
"""
if f.__doc__ is None:
fname = f.__name__
for c in getmro(A):
if hasattr(c, fname):
d = getattr(c, fname).__doc__
if d is not None:
f.__doc__ = d
break
return f
确实有效,但由于A
被硬编码到装饰器函数中,因为我找到了
无法知道传递给装饰器时附加了哪个类f
:
In [15]: class C(A):
....: @property
....: @inheritDocFromA
....: def a(self):
....: return False
....:
In [16]: C.a.__doc__
Out[16]: 'The a:ness of it'
问题: 是否有可能为类属性构建一个decorator应用文档字符串的通用解决方案而不需要在继承到装饰器函数中进行硬编码?
我也尝试过装饰课程,但后来我发现了文档字符串被写保护。
最后,如果可能,我希望解决方案适用于Python 2.7和3.4。
答案 0 :(得分:1)
可以编写一个装饰器,当通过类访问时返回正确的__doc__
- 毕竟,__get__
接收类型并可以通过其MRO,找到合适的__doc__
,并将其设置为自身(或在为此目的创建和返回的代理上)。但解决__doc__
不可写的问题要简单得多。
事实证明,由于property
是作为一种类型实现的,因此将其实例的__doc__
写为可写就像从它继承一样简单:
class property_writable_doc(property):
pass
然后,您使用类装饰器继承__doc__
属性的想法可以起作用:
def inherit_doc_class(cls):
for name, obj in cls.__dict__.iteritems():
if isinstance(obj, property_writable_doc) and obj.__doc__ is None:
for t in cls.__mro__:
if name in t.__dict__ and t.__dict__[name].__doc__ is not None:
obj.__doc__ = t.__dict__[name].__doc__
break
return cls
class A(object):
@property
def a(self):
"The a:ness of it"
return True
@inherit_doc_class
class B(A):
@property_writable_doc
def a(self):
return False
@inherit_doc_class
class C(A):
@property_writable_doc
def a(self):
"The C:ness of it"
return False