【发布时间】:2014-06-25 10:27:54
【问题描述】:
假设我有两个类(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'
问题: 是否可以为在类属性上应用装饰器的文档字符串构建一个通用解决方案,而无需在继承到装饰器函数中进行硬编码?
我也尝试过装饰类,但后来我遇到了属性文档字符串被写保护的问题。
最后,如果可能的话,我希望该解决方案同时适用于 Python 2.7 和 3.4。
【问题讨论】:
-
OT:当有类型对象的公共
__mro__属性时,为什么要使用inspect.getmro? AFAIKinspect最好保留用于没有用于访问某些功能的公共 API 或 API 是特定于 cpython 的情况。 -
一个解决方案是
<class>.a返回一个代理对象,其__doc__返回T.__dict__.a.__doc__,T 是<class>.__mro__中的第一个类型,其T.__dict__.a.__doc__不是None。这消除了继承层次结构的硬编码,这是您所要求的,但代价是引入了代理类和过度工程的味道。当我使用真正的键盘时,我会尝试将其写成答案。 -
@JamesMills 从那个问题接受的解决方案在这里不起作用。正如 OP 所指出的:我也尝试过装饰类,但后来我遇到了属性文档字符串被写保护的问题。
-
这里也一样.. 我自己也有一些想法。似乎他们在 Python 3 中解决了几个或更多关于此问题的问题......
标签: python python-decorators docstring