1

In the following code I have an object with two fields: a dictionary and an aggregator. The aggregator's goal is to give the sum of dictionary values in O(1) time. I thought to use properties in order to control the access to the fields, but the dict setter is never called:

class C:
    def __init__(self):
        self._p = dict()
        self._sum_of_p_values = 0

    def get_p(self):
        print('getting p')
        return self._p
    def set_p(self, v):
        print('setting p')
        self._p = v
        print('updating the sum')
        self._sum_of_p_values = sum(self._p.values())
    def get_sum_of_values(self):
        return self._sum_of_p_values
    p = property(get_p, set_p, None, None)
    sum_of_values = property(get_sum_of_values, None, None, None) #read-only property

c = C()
c.p['a'] = 1 #value created, expect to update the aggregator
c.p['b'] = 2.14 #value created, expect to update the aggregator
# I want c.sum_of_values to be 3.14
print(c.sum_of_values)

This is the output of the above code:

getting p
getting p
0

What is the best way to achieve my goal?

Boris Gorelik
  • 29,945
  • 39
  • 128
  • 170

1 Answers1

0

You are directly setting the properties instead of using your setter method. Try this one:

class C:
    def __init__(self):
        self._p = dict()
        self._sum_of_p_values = 0

    def get_p(self):
        print('getting p')
        return self._p
    def set_p(self, k, v):
        print('setting p')
        self._p[k] = v
        print('updating the sum')
        self._sum_of_p_values = sum(self._p.values())
    def get_sum_of_values(self):
        return self._sum_of_p_values
    p = property(get_p, set_p, None, None)
    sum_of_values = property(get_sum_of_values, None, None, None) #read-only property

c = C()

c.set_p('a', 1)  #value created, expect to update the aggregator
c.set_p('b', 2.14) #value created, expect to update the aggregator
# I want c.sum_of_values to be 3.14
print(c.sum_of_values)

If you don't want to call your setter directly, you can use this approach:

https://stackoverflow.com/a/5021107/2011147

Community
  • 1
  • 1
Selcuk
  • 57,004
  • 12
  • 102
  • 110
  • you are correct, I don't want to call setter directly, I want to keep the "clean" syntax. Otherwise one needs to remove the property definition for `p` in order to make sure no confusion is made. – Boris Gorelik Apr 02 '14 at 10:21