我正在尝试动态生成一些类定义(用于包装 C++ 扩展)。下面的描述符工作正常,除了当我尝试使用 help() 访问字段的文档字符串时,它提供描述符的默认文档而不是字段本身。但是,当我执行 help(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__
for help(class.field)
?
有没有办法绕过这个问题,并为 doc 提供类似 getter 函数的功能,而不必将 doc 字符串存储在描述符中?
like:
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)
问题是当我说:
help(DerivedClass.a)
Python 抛出异常表明我正在尝试调用None.get_field
. Thus help()
正在呼叫__get__
方法与obj=None
and dtype=DerivedClass
。这就是为什么我决定在 obj=None 且 dtype!=None 时返回 FieldDescriptor 实例。
我的印象是help(xyz)
尝试显示xyz.__doc__
。按照这个逻辑,如果__get__
回报descriptor_instance
, then descriptor_instance.__doc__
应该由help()打印,整个类都是这样[help(DerivedClass)
],但不适用于单个字段[help(DerivedClass.a)
].