在Python描述符中创建动态文档字符串 [英] Creating dynamic docstrings in Python descriptor
问题描述
我试图动态生成一些类定义(用于包装C ++扩展).以下描述符工作正常,除了当我尝试使用help()访问字段的文档字符串时,它为描述符提供了默认文档,而不是其自身的字段.但是,当我执行help(classname)时,它会检索传递给描述符的docstring:
I am trying to generate some class definitions dynamically (for wrapping a C++ extension). The following descriptor works fine except when I try to access the docstring for a field using help(), it gives default documentation for the descriptor rather than the field it self. However when I do help(classname), it retrieves the docstring passed to the descriptor:
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"打印:
"python test.py" prints:
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)
有人知道如何为help(class.field)
获取descriptor.__doc__
吗?
有没有一种方法可以绕过这个问题,并为文档提供类似getter函数的功能,而不必将doc字符串存储在描述符中?
Any idea how one can get the descriptor.__doc__
for help(class.field)
?
And is there a way to bypass this and have something like a getter function for doc in stead of having to store the doc string in the descriptor?
喜欢:
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__
的定义开始的:
UPDATE:
Actually I started with this definition of __get__
:
def __get__(self, obj, dtype=None):
return obj.get_field(self.name)
这个问题是当我说:
help(DerivedClass.a)
Python抛出一个异常,指示我正在尝试调用None.get_field
.因此,help()
正在使用obj=None
和dtype=DerivedClass
调用__get__
方法.这就是为什么我决定在obj = None和dtype!= None时返回FieldDescriptor实例的原因.
我的印象是help(xyz)
尝试显示xyz.__doc__
.按照这种逻辑,如果__get__
返回descriptor_instance
,则应该通过help()打印descriptor_instance.__doc__
,这对于整个类[help(DerivedClass)
]都是这种情况,但对于单个字段[help(DerivedClass.a)
]则不是
Python threw an Exception indicating that I was trying to call None.get_field
. Thus help()
is calling the __get__
method with obj=None
and dtype=DerivedClass
. That is why I decided to return the FieldDescriptor instance when obj=None and dtype!=None.
My impression was help(xyz)
tries to display xyz.__doc__
. By that logic, if __get__
returns descriptor_instance
, then descriptor_instance.__doc__
should be printed by help(), which is the case for the whole class [help(DerivedClass)
], but not for the single field [help(DerivedClass.a)
].
推荐答案
发生的事情是,当您请求help(DerivedClass.a)
时-python计算括号内的表达式-这是描述符的__get__
方法返回的对象-然后他们搜索该对象的帮助(包括文档字符串).
What goes on is that when you request help(DerivedClass.a)
- python calculates the expression inside the parentheses - which is the object returned by the descriptor's __get__
method - and them searchs for the help (including docstring) on that object.
进行此工作(包括动态docstring生成)的一种方法是让您的__get__
方法检索具有所需doc字符串的动态生成的对象.但是,此对象本身必须是原始对象的适当代理对象,并且会在代码上产生一些开销-以及许多特殊情况.
A way to have this working, including the dynamic docstring generation, is to have your __get__
method to retudn a dynamically generated object that features the desired doc string. But this object would itself need to be a proper proxy object to the original one, and would create some overhead on your code - and a lot of special cases.
无论如何,要使其正常工作的唯一方法就是修改__get__
本身返回的对象,以使它们的行为像您希望的那样.
Anyway, the only way to get it working ike you want is to modify the objects returned by __get__
itself, so that they behave like you'd like them to.
Id建议,如果您希望获得的帮助只是您所做的一些信息,也许您希望从__get__
返回的对象属于定义__repr__
方法的类(而不只是__doc__
字符串).
Id suggest that if all you want in the help is a bit of information like you are doing, maybe you want the objects returned from your __get__
to be of a class that define a __repr__
method (rather than just a __doc__
string) .
这篇关于在Python描述符中创建动态文档字符串的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!