Estoy intentando generar algunas definiciones de clase dinámicamente (para envolver una extensión de C++). El siguiente descriptor funciona bien, excepto cuando trato de acceder a la docstring para un campo usando help(), proporciona la documentación predeterminada para el descriptor en lugar del campo en sí. Sin embargo cuando hago ayuda (nombre de clase), recupera la cadena de documentación se pasa al descriptor:Creación de cadenas de documentos dinámicas en el descriptor de Python
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)
imprime "pitón" test.py:
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)
alguna idea de cómo se puede conseguir el descriptor.__doc__
para help(class.field)
? ¿Y hay alguna manera de eludir esto y tener algo así como una función getter para doc en lugar de tener que almacenar la cadena de documentación en el descriptor?
gustan:
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)
ACTUALIZACIÓN: En realidad empecé con esta definición de __get__
:
def __get__(self, obj, dtype=None):
return obj.get_field(self.name)
El problema con esto es que cuando dije:
help(DerivedClass.a)
Python lanzó una excepción que indica que estaba tratando de llamar al None.get_field
. Por lo tanto, help()
está llamando al método __get__
con obj=None
y dtype=DerivedClass
. Es por eso que decidí devolver la instancia de FieldDescriptor cuando obj = None y dtype! = None. Mi impresión fue help(xyz)
intenta mostrar xyz.__doc__
. Según esa lógica, si __get__
devuelve descriptor_instance
, entonces descriptor_instance.__doc__
se debe imprimir con ayuda(), que es el caso para toda la clase [help(DerivedClass)
], pero no para el campo único [help(DerivedClass.a)
].
Estoy seguro de que todo está ahí, pero ¿podría aclarar qué llamadas le están dando el resultado de ayuda incorrecto? Es demasiado esfuerzo adivinar lo que esperaba al leer el código. – alexis
Como señaló jsbueno, es la ayuda (DerivedClass.a) la que muestra la documentación del descriptor en lugar de la documentación del campo (guardada en el descriptor .__ doc__). – subhacom