Próbuję generować niektóre definicje klas dynamicznie (do pakowania rozszerzenia C++). Poniższy deskryptor działa dobrze, z wyjątkiem sytuacji, gdy próbuję uzyskać dostęp do docstringu dla pola za pomocą help(), to daje domyślną dokumentację dla deskryptora, a nie samego pola. Jednak kiedy robię pomocy (classname), pobiera docstring przekazany do Eurovoc:Tworzenie dynamicznych docstrings w deskryptorze 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)
"pyton test.py" drukuje:
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)
Każdy pomysł w jaki sposób można uzyskać descriptor.__doc__
dla help(class.field)
? I czy istnieje sposób, aby ominąć to i mieć coś w rodzaju funkcji gettera dla dokumentu zamiast przechowywania ciągu dokumentacyjnego w deskryptorze?
lubię:
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)
UPDATE: Właściwie zacząłem z tej definicji __get__
:
def __get__(self, obj, dtype=None):
return obj.get_field(self.name)
Problemem było to, że kiedy powiedział:
help(DerivedClass.a)
Python rzucił wyjątek wskazujący, że próbuję wywołać None.get_field
. Tak więc help()
wywołuje metodę __get__
z obj=None
i dtype=DerivedClass
. Dlatego zdecydowałem się zwrócić instancję FieldDescriptor, gdy obj = None i dtype! = None. Moje wrażenie było help(xyz)
próbuje wyświetlić xyz.__doc__
. Zgodnie z tą logiką, jeśli __get__
zwraca descriptor_instance
, wówczas descriptor_instance.__doc__
powinno zostać wydrukowane przez help(), co ma miejsce w przypadku całej klasy, ale nie w przypadku pojedynczego pola [].
Jestem pewien, że wszystko tam jest, ale czy mógłbyś wyjaśnić, które połączenia podają ci nieprawidłową pomoc? Zbyt wiele wysiłku, aby odgadnąć, czego się spodziewałeś czytając kod. – alexis
Jak jsbueno zwrócił uwagę, to jest to help (DerivedClass.a), który wyświetla dokumentację dla deskryptora zamiast dokumentacji dla pola (zapisanego w deskryptorze .__ doc__). – subhacom