我试图动态生成一些类定义(用于包装C ++扩展)。以下描述符工作正常,除非我尝试使用help()访问字段的docstring时,它为描述符而不是自己的字段提供默认文档。但是当我提供帮助(classname)时,它会检索传递给描述符的文档字符串:
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)
“python 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)
知道如何获得descriptor.__doc__
的{{1}}?
有没有办法绕过这个,并为doc提供类似getter函数的东西,而不必将doc字符串存储在描述符中?
像:
help(class.field)
更新:
实际上我从这个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)
:
__get__
问题在于我说:
def __get__(self, obj, dtype=None):
return obj.get_field(self.name)
Python抛出了一个Exception,表明我试图调用help(DerivedClass.a)
。因此None.get_field
使用help()
和__get__
调用obj=None
方法。这就是为什么我决定在obj = None和dtype!= None时返回FieldDescriptor实例。
我的展示是dtype=DerivedClass
试图显示help(xyz)
。按照这种逻辑,如果xyz.__doc__
返回__get__
,那么descriptor_instance
应该由help()打印,这是整个班级[descriptor_instance.__doc__
]的情况,但不是单个字段[help(DerivedClass)
]。
答案 0 :(得分:1)
当你请求help(DerivedClass.a)
时,python计算括号内的表达式 - 这是描述符的__get__
方法返回的对象 - 然后他们搜索帮助(包括docstring)在那个对象上。
使这项工作的方法,包括动态文档字符串生成,是让您的__get__
方法重新生成具有所需文档字符串的动态生成的对象。但是这个对象本身需要成为原始对象的正确代理对象,并且会在代码上产生一些开销 - 以及许多特殊情况。
无论如何,让你想要的唯一方法就是修改__get__
本身返回的对象,这样它们的行为就像你想要的那样。
我建议如果您在帮助中想要的只是一些信息,那么您可能希望从__get__
返回的对象属于定义__repr__
方法的类(而不仅仅是__doc__
字符串)。