Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 是否将docstring添加到_插槽_描述符?_Python - Fatal编程技术网

Python 是否将docstring添加到_插槽_描述符?

Python 是否将docstring添加到_插槽_描述符?,python,Python,我正在编写一个存储自动化模块,用于提供卷。我没有传递实际在存储控制器上创建卷所需的六个或更多参数,而是使用\uuuuu slots\uuuu创建了一个参数类,该参数类被传递到create方法中,如下所示: from mock import Mock from six import with_metaclass class VolumeParameterMeta(type): def __new__(mcs, name, bases, dct): # set __slot

我正在编写一个存储自动化模块,用于提供卷。我没有传递实际在存储控制器上创建卷所需的六个或更多参数,而是使用
\uuuuu slots\uuuu
创建了一个参数类,该参数类被传递到create方法中,如下所示:

from mock import Mock
from six import with_metaclass

class VolumeParameterMeta(type):
    def __new__(mcs, name, bases, dct):
        # set __slots__ docstrings here?
        return super(VolumeParameterMeta, mcs).__new__(mcs, name, bases, dct)

class VolumeParameter(with_metaclass(VolumeParameterMeta, object)):
    __slots__ = ('name', 'size', 'junctionPath', 'svmName', 'securityStyle'
                 'spaceReserve')

    def __init__(self, name):
        self.name = name

class Volume(object):
    def __init__(self, driver, name):
        self.driver = driver
        self.name = name

    @classmethod
    def create(cls, driver, param):
        # do sanity check on param (volume not too large, etc)
        driver.provision(param)
        return cls(driver, param.name)

if __name__ == '__main__':
    param = VolumeParameter('volume1')
    param.svmName = 'vserver1'
    param.junctionPath = '/some/path'
    param.size = 2 ** 30
    param.spaceReserve = param.size * 0.1
    param.securityStyle = 'mixed'
    volume = Volume.create(driver=Mock(), param=param)
上面的示例非常有效,但有一个小的例外。如何将docstring添加到参数类中的描述符并不明显。看起来元类应该是可以的,但是元类实例化时没有定义描述符

我清楚地意识到,有些人可能不同意我使用
\uuuuu slots\uuuuu
的副作用,但我喜欢它有助于消除打字错误。尝试设置一个不存在的参数,并弹出
AttributeError
。都没有任何样板代码。可以说,让它在卷创建时失败更像python,但结果将是使用默认值而不是拼写错误的参数。这实际上是一次无声的失败

我意识到可以简单地扩展参数类docstring,但是
pydoc
和其他文档构建脚本的结果是类的大型自由格式docstring和每个描述符的空docstring


肯定有办法为
创建的描述符定义docstring吗?也许除了吃角子老虎还有别的办法?一个可变的
名称双倍
或类似的?

否,没有选项将docstring添加到为
\uuuuu slots\uuu
中定义的名称生成的描述符对象中。在这方面,它们类似于常规的非描述符属性

在没有插槽的常规对象上,最多可以添加注释并设置默认值:

class VolumeParameter(object):
     # the name of the volume (str)
     name = ''
     # volume size in bytes (int)
     size = 0
     # ...
即使您将所有这些属性声明为
\uuuuu插槽\uuuu
,也同样适用

您可以将每个插槽以
属性
对象的形式“包装”到另一个描述符中:

class VolumeParameterMeta(type):
    @staticmethod
    def _property_for_name(name, docstring):
        newname = '_' + name
        def getter(self):
            return getattr(self, newname)
        def setter(self, value):
            setattr(self, newname, value)
        def deleter(self):
            delattr(self, newname)
        return newname, property(getter, setter, deleter, docstring)

    def __new__(mcs, name, bases, dct):
        newslots = []
        clsslots = dct.pop('__slots__', ())
        slotdocs = dct.pop('__slot_docs__', {})
        if isinstance(clsslots, str):
            clsslots = clsslots.split()
        for name in clsslots:
            newname, prop = mcs._property_for_name(name, slotdocs.get(name))
            newslots.append(newname)
            dct[name] = prop
        if newslots:
            dct['__slots__'] = tuple(newslots)
        return super(VolumeParameterMeta, mcs).__new__(mcs, name, bases, dct)

class VolumeParameter(with_metaclass(VolumeParameterMeta, object)):
    __slots__ = ('name', 'size', 'junctionPath', 'svmName', 'securityStyle'
                 'spaceReserve')
    __slot_docs__ = {
        'name': 'the name of the volume (str)',
        # ...
    }
请注意,这几乎使类上的描述符数量增加了一倍:

>>> pprint(VolumeParameter.__dict__)
mappingproxy({'__doc__': None,
              '__module__': '__main__',
              '__slots__': ('_name',
                            '_size',
                            '_junctionPath',
                            '_svmName',
                            '_securityStylespaceReserve'),
              '_junctionPath': <member '_junctionPath' of 'securityStylespaceReserve' objects>,
              '_name': <member '_name' of 'securityStylespaceReserve' objects>,
              '_securityStylespaceReserve': <member '_securityStylespaceReserve' of 'securityStylespaceReserve' objects>,
              '_size': <member '_size' of 'securityStylespaceReserve' objects>,
              '_svmName': <member '_svmName' of 'securityStylespaceReserve' objects>,
              'junctionPath': <property object at 0x105edbe08>,
              'name': <property object at 0x105edbd68>,
              'securityStylespaceReserve': <property object at 0x105edb098>,
              'size': <property object at 0x105edbdb8>,
              'svmName': <property object at 0x105edb048>})

感谢您的解答和解释!
>>> VolumeParameter.name.__doc__
'the name of the volume (str)'