0

我有这个(Py2.7.2):

class MyClass(object):
    def __init__(self, dict_values):
        self.values = dict_values
        self.changed_values = {} #this should track changes done to the values{}
        ....

我可以这样使用它:

var = MyClass()
var.values['age'] = 21
var.changed_values['age'] = 21

但我想像这样使用它:

var.age = 21
print var.changed_values #prints {'age':21}

我怀疑我可以使用属性来做到这一点,但如何?

更新:

我在设计时不知道 dict 内容。它只会在运行时知道。它可能不会为空

4

3 回答 3

1

您可以创建一个从 dict 继承的类并覆盖所需的函数

class D(dict):
    def __init__(self):
        self.changed_values = {}
        self.__initialized = True

    def __setitem__(self, key, value):
        self.changed_values[key] = value
        super(D, self).__setitem__(key, value)

    def __getattr__(self, item):
        """Maps values to attributes.
        Only called if there *isn't* an attribute with this name
        """
        try:
            return self.__getitem__(item)
        except KeyError:
            raise AttributeError(item)

    def __setattr__(self, item, value):
        """Maps attributes to values.
        Only if we are initialised
        """
        if not self.__dict__.has_key('_D__initialized'):  # this test allows attributes to be set in the __init__ method
            return dict.__setattr__(self, item, value)
        elif self.__dict__.has_key(item):       # any normal attributes are handled normally
            dict.__setattr__(self, item, value)
        else:
            self.__setitem__(item, value)

a = D()
a['hi']  = 'hello'
print a.hi
print a.changed_values

a.hi = 'wow'
print a.hi
print a.changed_values

a.test = 'test1'
print a.test
print a.changed_values

输出

>>hello
>>{'hi': 'hello'}
>>wow
>>{'hi': 'wow'}
>>test1
>>{'hi': 'wow', 'test': 'test1'}
于 2012-09-25T15:15:47.750 回答
0

只有当要监视的属性集是有界的时,属性(实际上是描述符)才会有所帮助。__set__()只需在描述符的方法中归档新值即可。

如果属性集是任意的或无界的,那么您将需要覆盖MyClass.__setattr__()

于 2012-09-25T15:15:35.280 回答
0

您可以使用property()内置功能。

这比覆盖__getattr__and更可取__setattr__,如此所述。

  class MyClass:  

      def __init__(self):
          self.values = {}
          self.changed_values = {}

      def set_age( nr ):
           self.values['age'] = nr
           self.changed_values['age'] = nr

      def get_age():
           return self.values['age']

      age = property(get_age,set_age)
于 2012-09-25T15:15:55.247 回答