Home > OS >  Keep the sum of two objects updated as one (or both) objects gets updated
Keep the sum of two objects updated as one (or both) objects gets updated

Time:01-19

I want to create a class in Python that implements a __add__ object method that allows summing two objects of the same class. Let's call this class Indicator and the two objects to sum ind1 and ind2. The Indicator object has only one property elements , which is a dictionary of integer values.

My implementation of __add__ combines the elements properties of two objects, eventually summing those values with the same key.

from __future__ import annotations
import copy
class Indicator:
    def __init__(self, elements={}):
        self.elements = elements

    def __add__(self, other: Indicator):
        new = copy.deepcopy(self)
        new.values =  {k: self.elements.get(k, 0)   other.elements.get(k, 0) for k in set(self.elements) | set(other.elements)}
        return new

ind1 = Indicator({1:1,2:2,3:3})
ind2 = Indicator({1:1,2:2})

new = ind1   ind2
print('ind1: ',ind1.elements)
print('ind2: ',ind2.elements)
print(new.elements) # {1: 2, 2: 4, 3: 3}

I would like __add__ to return an object whose elements property gets updated as one or both objects in the summation get updated along the code flow.

For example,

ind1.elements[4] = 4
print(new.elements) # I would like this to be {1: 2, 2: 4, 3: 3, 4:4}

ind1.elements[1] = 3
print(new.elements) # I would like this to be {1: 4, 2: 4, 3: 3, 4:4}

How can I do it?

CodePudding user response:

A very rough idea how this can be done (with a lot of work left to you):

class dict_obs(dict):
    def __init__(self, observer, *args, **kwargs):
        self._observer = observer
        super().__init__(*args, **kwargs)

    def __setitem__(self, key, value):
        self._observer.notify(key)
        super().__setitem__(key, value)


class Indicator:
    def notify(self, key):
        print(f"{key} changed")



observer = Indicator()

d = dict_obs(observer, {1:1,2:2,3:3})

d[2] = 5

Prints

2 changed

CodePudding user response:

Your issue is with this line:

new.values =  {k: self.elements.get(k, 0)   other.elements.get(k, 0) for k in set(self.elements) | set(other.elements)}

You are creating sets of k:v pairs when you really only want the keys. Here is a working solution:

class Indicator:
    def __init__(self, elements={}):
        self.elements = elements
    
    def __add__(self, other):
        keys = set(self.elements.keys()).union(set(other.elements.keys()))
        new = {}
        for k in keys:
            new[k] = self.elements.get(k,0)   other.elements.get(k,0)
        return Indicator(new)
  • Related