通过属性公开dict值

时间:2012-09-25 15:07:38

标签: python

我有这个(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}

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

更新

我不知道设计时的字典内容。它只在运行时才知道。它可能不会是空的

3 个答案:

答案 0 :(得分: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'}

答案 1 :(得分:0)

属性(描述符,真的)只有在要监视的属性集有界时才有用。只需在描述符的__set__()方法中提交新值即可。

如果属性集是任意的或无限制的,那么您将需要过度使用MyClass.__setattr__()

答案 2 :(得分:0)

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

如首字母here所述,我们首选覆盖__getattr____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)