Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/grails/5.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属性工厂或描述符类_Python_Properties_Factory_Descriptor_Python.net - Fatal编程技术网

用于包装外部库的Python属性工厂或描述符类

用于包装外部库的Python属性工厂或描述符类,python,properties,factory,descriptor,python.net,Python,Properties,Factory,Descriptor,Python.net,我正在为通过Pythonnet访问的C#API编写一个Python包装类。 由于我想用我自己的方法扩展API,我决定使用下面概述的组合方法对其进行包装: C#API大量使用了我希望在Python代码中模拟的属性。下面的最小示例显示了我当前对具有两个属性宽度和高度的C#曲面类示例的方法: class MySurface: def __init__(api_surface): self.api_surface = api_surface @property

我正在为通过Pythonnet访问的C#API编写一个Python包装类。 由于我想用我自己的方法扩展API,我决定使用下面概述的组合方法对其进行包装:

C#API大量使用了我希望在Python代码中模拟的属性。下面的最小示例显示了我当前对具有两个属性宽度和高度的C#曲面类示例的方法:

class MySurface:
    def __init__(api_surface):
        self.api_surface = api_surface
    
    @property
    def width(self):
        return self.api_surface.width

    @width.setter
    def width(self, value):
        self.api_surface.width = value

    @property
    def height(self):
        return self.api_surface.height

    @height.setter
    def height(self, value):
        self.api_surface.height = value
我总共要处理大约50处房产。对于多组属性,我希望添加自己的错误检查、类型转换等。 我要寻找的是一种定义属性的Pythonic方法,例如通过工厂或使用描述符。谢谢你的帮助


编辑:我希望能够在python shell(即surface)中使用制表符补全。{hit tab}应建议surface.width和surface.height。这似乎不可能通过Greg概述的getattr方法实现。

如果要避免所有手动编码,您可以使用getattr和setattr。这个答案将适用于python2顺便说一句

class MySurface(object):
    def __init__(self):
        self.props = {"width": 0, "length": 0, ...}

    def __setattr__(self, attr, val):
        if attr in self.props:
            self.props[attr] = val
        else:
            super(MySurface, self).__setattr__(attr, val)

    def __getattr__(self, attr):
        if attr in self.props:
           return self.props[attr]
        else:
           return self.__getattribute__(attr)

我能够使用以下属性工厂解决问题:

def surface_property(api_property_name, docstring=None):
    def getter(self):
        return self.api_surface.__getattribute__(api_property_name)

    def setter(self, value):
        self.api_surface.__setattr__(api_property_name, value)

    return property(getter, setter, doc=docstring)
使用此函数,类定义减少为:

class MySurface:
    def __init__(api_surface):
        self.api_surface = api_surface

    width = surface_property('Width','Get and set the width.')
    height = surface_property('height', 'Get and set the height.')

我已经尝试过类似的方法。我的主要目标之一是在交互式Python会话中使用包装的类时有适当的代码完成(制表符完成)。这似乎不适用于用户必须提前知道attibute名称的概述方法。您的问题中可能应该包括这一点。除了手动定义所有属性之外,我想不出还有什么可以做的了。这是Python中替代组合模式的一个很好的例子(而不是使用
\uuuuu getattr\uuuuu
\uuuuu setattr\uuuuu
将属性查找委托给成员)。