2

在一个类中,我想定义 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")

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

4

2 回答 2

3

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

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
于 2013-10-16T17:15:00.093 回答
1

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

于 2013-10-16T17:02:40.930 回答