假设我有两个类(AB),其中第二个类是从第一个类派生的。此外,我通过在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'


问:是否可以为类属性上的装饰器应用文档字符串构造通用解决方案,而无需在装饰器函数的继承中进行硬编码?

我也尝试过装饰类,但是后来我的属性docstrings被写保护了。

最后,如果可能的话,我希望该解决方案适用于Python 2.7和3.4。

最佳答案

可以编写通过类访问时返回正确的__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

关于python - 如何使用装饰器自动记录我的类(class)属性,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/24406190/

10-15 23:35