【问题标题】:Implementing Python persistent properties实现 Python 持久属性
【发布时间】:2013-10-24 21:41:19
【问题描述】:

在一个类中,我想定义 N 个持久属性。我可以按如下方式实现它们:

@property
def prop1(self):
    return self.__prop1
@prop1.setter
def prop1(self, value):
    self.__prop1 = value
    persistenceManagement()        

@property
def prop2(self):
    return self.__prop2
@prop2.setter
def prop2(self, value):
    self.__prop2 = value
    persistenceManagement()       

[...]

@property
def propN(self):
    return self.__propN
@propN.setter
def propN(self, value):
    self.__propN = value
    persistenceManagement()       

当然,这些块之间唯一不同的是属性名称(prop1、prop2、...、propN)。 persistenceManagement() 是一个函数,当这些属性之一的值发生变化时必须调用它。

由于除了单个信息(即属性名称)之外,这些代码块是相同的,我想必须有某种方法可以用单行替换这些代码块中的每一个,以声明具有给定名称的持久属性的存在.类似的东西

def someMagicalPatternFunction(...):
     [...]


someMagicalPatternFunction("prop1")
someMagicalPatternFunction("prop2")
[...]
someMagicalPatternFunction("propN")

...或者可能是我目前看不到的一些装饰技巧。有人知道如何做到这一点吗?

【问题讨论】:

  • 那么您要做的就是在设置任何这些属性后运行一个函数,对吧?
  • @Blender Well... 自动声明 setter 和 getter + 为 setter 添加一行代码以实现持久性。
  • @martineau 我责怪复制和粘贴。感谢您的关注。我已经编辑了问题。

标签: python properties persistence decorator


【解决方案1】:

property 类(是的,它是一个类)只是descriptor 协议的一种可能实现(此处有完整文档:http://docs.python.org/2/howto/descriptor.html)。只需编写您自己的自定义描述符即可。

【讨论】:

    【解决方案2】:

    属性只是descriptor 类,您可以创建自己的并使用它们:

    class MyDescriptor(object):
        def __init__(self, name, func):
            self.func = func
            self.attr_name = '__' + name
        def __get__(self, instance, owner):
            return getattr(self, self.attr_name)
        def __set__(self, instance, value):
            setattr(self, self.attr_name, value)
            self.func(self.attr_name)
    
    def postprocess(attr_name):
        print 'postprocess called after setting', attr_name
    
    class Example(object):
        prop1 = MyDescriptor('prop1', postprocess)
        prop2 = MyDescriptor('prop2', postprocess)
    
    obj = Example()
    obj.prop1 = 'answer'  # prints 'postprocess called after setting __prop1'
    obj.prop2 = 42  # prints 'postprocess called after setting __prop2'
    

    您可以选择使用以下方式使其更易于使用:

    def my_property(name, postprocess=postprocess):
        return MyDescriptor(name, postprocess)
    
    class Example(object):
        prop1 = my_property('prop1')
        prop2 = my_property('prop2')
    

    如果你喜欢装饰器@ 语法,你可以这样做(这也减轻了两次键入属性名称的麻烦)——但是它需要的虚拟函数看起来有点奇怪......

    def my_property(method):
        name = method.__name__
        return MyDescriptor(name, postprocess)
    
    class Example(object):
        @my_property
        def prop1(self): pass
        @my_property
        def prop2(self): pass
    

    【讨论】:

    • 谢谢。很有启发性。
    猜你喜欢
    • 2015-01-05
    • 2010-09-29
    • 1970-01-01
    • 2012-01-09
    • 1970-01-01
    • 2013-08-23
    • 2016-06-11
    • 1970-01-01
    • 2013-11-06
    相关资源
    最近更新 更多