在 Python 描述符中创建动态文档字符串

2023-12-30

我正在尝试动态生成一些类定义(用于包装 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)].


发生的事情是当你请求时help(DerivedClass.a)- python 计算括号内的表达式 - 这是描述符返回的对象__get__方法 - 他们搜索该对象的帮助(包括文档字符串)。

实现此功能(包括动态文档字符串生成)的一种方法是让您的__get__方法来重新生成具有所需文档字符串的动态生成的对象。但是这个对象本身需要成为原始对象的适当代理对象,并且会给您的代码带来一些开销 - 以及许多特殊情况。

无论如何,让它像你想要的那样工作的唯一方法是修改返回的对象__get__本身,以便它们表现得像您希望的那样。

我建议,如果您在帮助中想要的只是像您正在做的那样的一些信息,也许您希望从您的__get__属于定义一个的类__repr__方法(而不仅仅是一个__doc__细绳) 。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 Python 描述符中创建动态文档字符串 的相关文章

随机推荐