【问题标题】:Python property factory or descriptor class for wrapping an external library用于包装外部库的 Python 属性工厂或描述符类
【发布时间】:2016-08-03 12:25:56
【问题描述】:

我正在为通过 Pythonnet 访问的 C# API 编写 Python 包装类。 由于我想用自己的方法扩展 API,我决定使用here 概述的组合方法来包装它:

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

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 中使用制表符完成,即表面。 {hit tab} 应该建议surface.width 和surface.height。 Greg 概述的 getattr 方法似乎无法做到这一点。

【问题讨论】:

    标签: python properties factory descriptor python.net


    【解决方案1】:

    如果您想避免所有手动编码,您可以只使用 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)
    

    【讨论】:

    • 我已经尝试过类似的方法。我的主要目标之一是在交互式 Python 会话中使用包装类时具有适当的代码完成(制表符完成)。这似乎不适用于用户必须提前知道属性名称的概述方法。
    • 应该在你的问题中包含这个。除了手动定义所有属性之外,我想不出你能做的更多
    【解决方案2】:

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

    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 中替代组合模式的一个非常好的示例(而不是使用 __getattr____setattr__ 将属性查找委托给成员)。
    • 有没有什么方法可以从 api_surface 的属性中复制文档字符串?
    猜你喜欢
    • 2014-06-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-02
    • 1970-01-01
    • 2012-05-19
    • 1970-01-01
    相关资源
    最近更新 更多