I am trying to generate some class definitions dynamically (to wrap a C ++ extension). The following descriptor works fine, unless I try to access a docstring for a field using help (), it provides the default documentation for the descriptor, not the field. However, when I help (classname), it retrieves the docstring passed to the handle:
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(va)
"python test.py" outputs:
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)
Any idea how to get descriptor.__doc__
for help(class.field)
? And is there a way around this and have something like getter function for doc instead of storing doc string in descriptor?
as:
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)
UPDATE: Actually, I started with this __get__
definition:
def __get__(self, obj, dtype=None): return obj.get_field(self.name)
The problem with this was that when I said:
help(DerivedClass.a)
Python None.get_field
exception indicating that I was trying to call None.get_field
. So help()
calls the __get__
method with obj=None
and dtype=DerivedClass
. That is why I decided to return an instance of FieldDescriptor when obj = None and dtype! = None. My impression is: help(xyz)
trying to display xyz.__doc__
. By this logic, if __get__
returns descriptor_instance
, then descriptor_instance.__doc__
should be printed using help (), which is the case for the entire [ help(DerivedClass)
] class, but not for the single [ help(DerivedClass.a)
] field.