In Python, suppose you want to implement a class which has a dynamically generated docstring. The easiest way to do this would be to use the @property decorator for the __doc__ attribute. (You also need your class to be a “new-style” class, i.e., inherit from object). For example:
class A(object):
"""Docstring for class."""
def __init__(self, x):
self.x = x
@property
def __doc__(self):
return "My value of x is %s." % self.x
This gives the desired result:
>>> a = A(10) >>> print(a.__doc__) My value of x is 10.
But hides the docstring for the class A:
>>> A.__doc__ <property at 0x2083db8>
Read on to see how we can fix this.
To fix this, we can implement a custom class implementing the descriptor protocol. The default property descriptor behaves as:
class Property(object):
...
def __get__(self, obj, objtype=None):
if obj is None:
return self
if self.fget is None:
raise AttributeError, "unreadable attribute"
return self.fget(obj)
Here we see that if `obj is None`, that is, if we attempt to access `__doc__` on the class itself the property descriptor returns itself. To solve our problem we can instead return a string, perhaps something like:
class DocstringProperty(object):
def __init__(self, fget, class_doc):
self.fget = fget
self.class_doc = class_doc
def __get__(self, obj, objtype=None):
if obj is None:
return self.class_doc
else:
return self.fget(obj)
I’ve provided a fuller implementation and a function decorator in gist #4041015.
For example:
>>> class A(object): ... """Main docstring""" ... def __init__(self, x): ... self.x = x ... @docstring_property(__doc__) ... def __doc__(self): ... return "My value of x is %s." % self.x >>> A.__doc__ 'Main docstring' >>> a = A(10) >>> print(a.__doc__) My value of x is 10.