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.