Note that there are some explanatory texts on larger screens.

plurals
  1. POCreating dynamic docstrings in Python descriptor
    primarykey
    data
    text
    <p>I am trying to generate some class definitions dynamically (for wrapping a C++ extension). The following descriptor works fine except when I try to access the docstring for a field using help(), it gives default documentation for the descriptor rather than the field it self. However when I do help(classname), it retrieves the docstring passed to the descriptor:</p> <pre><code>class FieldDescriptor(object): def __init__(self, name, doc='No documentation available.'): self.name = name self.__doc__ = doc def __get__(self, obj, dtype=None): if obj is None and dtype is not None: print 'Doc is:', self.__doc__ return self return obj.get_field(self.name) def __set__(self, obj, value): obj.set_field(self.name, value) class TestClass(object): def __init__(self): self.fdict = {'a': None, 'b': None} def get_field(self, name): return self.fdict[name] def set_field(self, name, value): self.fdict[name] = value fields = ['a', 'b'] def define_class(class_name, baseclass): class_obj = type(class_name, (baseclass,), {}) for field in fields: setattr(class_obj, field, FieldDescriptor(field, doc='field %s in class %s' % (field, class_name))) globals()[class_name] = class_obj if __name__ == '__main__': define_class('DerivedClass', TestClass) help(DerivedClass.a) help(DerivedClass) v = DerivedClass() help(v.a) </code></pre> <p>"python test.py" prints:</p> <pre> Doc is: field a in class DerivedClass Help on FieldDescriptor in module __main__ object: class FieldDescriptor(__builtin__.object) | Methods defined here: | | __get__(self, obj, dtype=None) | | __init__(self, name, doc='No documentation available.') | | __set__(self, obj, value) | | ---------------------------------------------------------------------- | Data descriptors defined here: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) Doc is: field a in class DerivedClass Doc is: field b in class DerivedClass Help on class DerivedClass in module __main__: class DerivedClass(TestClass) | Method resolution order: | DerivedClass | TestClass | __builtin__.object | | Data descriptors defined here: | | a | field a in class DerivedClass | | b | field b in class DerivedClass | | ---------------------------------------------------------------------- | Methods inherited from TestClass: | | __init__(self) | | get_field(self, name) | | set_field(self, name, value) | | ---------------------------------------------------------------------- | Data descriptors inherited from TestClass: | | __dict__ | dictionary for instance variables (if defined) | | __weakref__ | list of weak references to the object (if defined) Help on NoneType object: class NoneType(object) | Methods defined here: | | __hash__(...) | x.__hash__() hash(x) | | __repr__(...) | x.__repr__() repr(x) </pre> <p>Any idea how one can get the <code>descriptor.__doc__</code> for <code>help(class.field)</code> ? And is there a way to bypass this and have something like a getter function for doc in stead of having to store the doc string in the descriptor?</p> <p>like:</p> <pre><code>class FieldDescriptor(object): def __init__(self, name, doc='No documentation available.'): self.name = name self.__doc__ = doc def __get__(self, obj, dtype=None): if obj is None and dtype is not None: print 'Doc is:', self.__doc__ return self return obj.get_field(self.name) def __set__(self, obj, value): obj.set_field(self.name, value) # This is what I'd like to have def __doc__(self, obj, dtype): return dtype.generate_docstring(self.name) </code></pre> <p>UPDATE: Actually I started with this definition of <code>__get__</code>:</p> <pre><code>def __get__(self, obj, dtype=None): return obj.get_field(self.name) </code></pre> <p>The problem with this was that when I said:</p> <pre><code>help(DerivedClass.a) </code></pre> <p>Python threw an Exception indicating that I was trying to call <code>None.get_field</code>. Thus <code>help()</code> is calling the <code>__get__</code> method with <code>obj=None</code> and <code>dtype=DerivedClass</code>. That is why I decided to return the FieldDescriptor instance when obj=None and dtype!=None. My impression was <code>help(xyz)</code> tries to display <code>xyz.__doc__</code>. By that logic, if <code>__get__</code> returns <code>descriptor_instance</code>, then <code>descriptor_instance.__doc__</code> should be printed by help(), which is the case for the whole class [<code>help(DerivedClass)</code>], but not for the single field [<code>help(DerivedClass.a)</code>].</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload