sub*_*com 8 python metaprogramming descriptor
我试图动态生成一些类定义(用于包装C++扩展).以下描述符工作正常,除非我尝试使用help()访问字段的docstring时,它为描述符而不是自己的字段提供默认文档.但是当我做帮助(classname)时,它会检索传递给描述符的docstring:
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)
Run Code Online (Sandbox Code Playgroud)
"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__的help(class.field)?是否有一种方法可以绕过这个并为doc提供类似getter函数的东西,而不必将doc字符串存储在描述符中?
喜欢:
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)
Run Code Online (Sandbox Code Playgroud)
更新:其实我从这个定义开始__get__:
def __get__(self, obj, dtype=None):
return obj.get_field(self.name)
Run Code Online (Sandbox Code Playgroud)
问题是当我说:
help(DerivedClass.a)
Run Code Online (Sandbox Code Playgroud)
Python抛出一个Exception表示我试图调用None.get_field.因此用和help()调用__get__方法.这就是为什么我决定在obj = None和dtype!= None时返回FieldDescriptor实例.我的印象是试图展示.通过该逻辑,如果返回,那么应该由help()打印,这是整个类[ ]的情况,但不是单个字段[ ].obj=Nonedtype=DerivedClasshelp(xyz)xyz.__doc____get__descriptor_instancedescriptor_instance.__doc__help(DerivedClass)help(DerivedClass.a)
发生的事情是,当您请求时help(DerivedClass.a)- python 计算括号内的表达式 - 这是描述符__get__方法返回的对象 - 并且它们搜索该对象的帮助(包括文档字符串)。
实现此功能(包括动态文档字符串生成)的一种方法是让您的__get__方法重新生成具有所需文档字符串的动态生成的对象。但是这个对象本身需要成为原始对象的适当代理对象,并且会给您的代码带来一些开销 - 以及许多特殊情况。
不管怎样,让它像你想要的那样工作的唯一方法是修改它本身返回的对象__get__,以便它们的行为像你希望的那样。
我建议,如果您在帮助中想要的只是像您正在做的那样的一些信息,也许您希望从您返回的对象__get__属于定义方法__repr__(而不仅仅是__doc__字符串)的类。
| 归档时间: |
|
| 查看次数: |
1799 次 |
| 最近记录: |