Implementing a class property that preserves the docstring

折月煮酒 提交于 2019-12-01 19:18:41

Indeed, test is a property returning a string. You'd have to subclass str and give that a __doc__ attribute:

class docstring_str(str):
    def __new__(cls, v, __doc__=''):
        s = super(docstring_str, cls).__new__(cls, v)
        s.__doc__ = __doc__
        return s

Demo:

>>> class docstring_str(str):
...     def __new__(cls, v, __doc__=''):
...         s = super(docstring_str, cls).__new__(cls, v)
...         s.__doc__ = __doc__
...         return s
... 
>>> s = docstring_str('Test', 'docstring')
>>> s
'Test'
>>> s.__doc__
'docstring'

Use as:

class A(object):
    @classproperty
    def test(cls):
        return docstring_str("Test", "docstring')

Because str objects are immutable, you cannot set the __doc__ attribute in a decorator. You'd have to return a proxy object instead that fully wraps the actual return value except for the __doc__ attribute. This gets to be complex and ugly fast.

The alternative is to put a regular property on the metaclass; the class's class:

class MetaClass(type):
    @property
    def test(cls):
        "docstring"
        return "Test"

class A(object):
    __metaclass__ = MetaClass

Now A has a test property, and the docstring can be accessed as MetaClass.test.__doc__ or with type(A).test.__doc__:

>>> A.test
'Test'
>>> type(A).test
<property object at 0x10757d158>
>>> type(A).test.__doc__
'docstring'

If you jump through a few hoops, it can be retrieved, but not directly through the property itself like A.test.__doc__ because of the way descriptors work.

class classproperty(object):
    def __init__(self, getter):
        self.getter = getter

    def __get__(self, instance, owner):
        if instance is None:  # instance attribute accessed on class?
            return self
        return self.getter(owner)

class A(object):
    @classproperty
    def test(cls):
        "test's docstring"
        return "Test"

def docstring(cls, methodname):
    return getattr(cls, methodname).getter.__doc__

print docstring(A, 'test')  # -> test's docstring
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!