[Tutor] Set/get doc strings of ALL attributes?

Gonçalo Rodrigues op73418 at mail.telepac.pt
Wed Nov 17 13:52:36 CET 2004

pan at uchicago.edu wrote:

> Hi there,
> I've been wondering if there's a way to set/get doc string
> for ALL elements of a class (but not just the __doc__ of
> function/method).

No. Imagine the following:

 >>> class Test(object):
... 	clsAttrib = 1
 >>> Test
<class '__main__.Test'>
 >>> Test.clsAttrib

clsAttrib is simply an attribute with no attached __doc__. If you do 
want to attach docstring to simple attributes you have to "wrap" the 
attribute in what is called a descriptor.

> I ended writing a class BaseObject for this purpose. It stores doc 
> strings of variables (that is, the <name> that is assigned to a 
> class using myclass.name). When asking for all docs, doc strings 
> are collected from 3 different sources:
> 1) property __doc__;
> 2) the variables mentioned above;
> 3) function/method __doc__;
> It seems to work well. My questions:
> A) Will the above approach be able to cover all elements 
>    such that an automatic documentation mechinsm can be
>    programmed?


> B) Is there any other better way to do this?

Yes -- see below.

> C) I intend to use this class as the base class for all 
>    other subclass. Will this kind of design cause any problem 
>    in any class inherited from it?

Yes, because you do *not* want inheritance here -- see below.

> Thx in advance.
> pan

I have not tested your code, but I think it is not going to work, 
because there are (at least) two problems with it. Warning: we are 
dangerously entering metaclass programming, so I'm just going to go 
ahead without too many explanations. If you can't follow me just holler.

> Here's the code:
> class BaseObject(object):

This is the first problem. Think about what you want to do: you want to 
control the setting of elements in *the class*. If you want to control 
the setting of attributes in an instance of some class you override 
__setattr__ of *the class*, in this case, the class of a class, so what 
you want is a *metaclass*. So it should be:

class MetaCls(type):

You have to alter some stuff below because of this, I'll leave that for 
now and jump to the second main problem.

>   '''An extention of class object, have the capacity of storing/retrieving
>      doc string for variables. Doc strings are retrievd from 3 different
>      elements: variable (name), property, and method (or function). See
>      the code in getDoc() for how to retrieve them.
>   '''
>   def __init__(self):
>      object.__init__(self)
>      self.__docs__ ={'__docs__':'An internal dict storing doc'
>      ' string of variables. Write: setattr(name, val, doc) or'
>      ' setDoc(name, doc), read: getDoc(name) or getDocs().'
>      ' Defined in class BaseObject.'}
>   def setattr(self, name, val, doc=None):
>      '''setattr(name, val, doc=None): set value and doc string 
>       of a variable <name>. If doc=None, doc is not changed
>       Defined in class BaseObject.''' 
>      if doc!=None: self.__docs__[name] = doc
>      self.__setattr__(name,val)
>      return self

This is the second problem: When you're doing an assignment as

cls.attribute = value

this ends up calling

cls.__class__.__setattr__(name, val)

Note the signature: the default value is never passed so the above will 
never work. What you want here is to *wrap* the attribute in a 
descriptor so that it can gain a docstring. Check the docs for a primer 
on descriptors. After it, if you have any doubts just holler.

Note: This is already advanced stuff, so you may want to go at 
comp.lang.python for further help.

With my best regards,
G. Rodrigues

More information about the Tutor mailing list