Search code examples
pythonmagic-methods

Indirect __iadd__ method combined with __setitem__


I have something like this:

 class Foo:
    def __init__(self):
       self.bar = ...

    def __setitem__(self, key, value=None) :
       self.bar[key] = value

Now I want:

  f = Foo()
  f['shmoo'] += 5

to do:

  f.bar['shmoo'] += 5

there is:

  def __iadd__(self,other): .....

but there the 'key' is not available. Any way to solve this?


Solution

  • f.['shmoo'] += 5 does the augmented assignment operation on the value in the collection (f.['shmoo']), not the collection itself. The pseudocode is

    val = f.__getitem__('shmoo')
    val += 5
    f.__setitem('shmoo', val)
    

    Implement __getitem__ but there is no need to implememnt __iadd__ and friends.

    We can demonstrate by adding some prints to Foo and creating a new class for the value.

    class Foo:
    
        def __init__(self):
            self.bar = {}
    
        def __getitem__(self, name):
            print("foo get", name)
            return self.bar[name]
    
        def __setitem__(self, name, value):
            print('foo set', name, value)
            self.bar[name] = value
    
    class Baz:
    
        def __init__(self):
            self.val = 0
    
        def __iadd__(self, other):
            self.val = self.val + other
            print("baz iadd", other, self.val)
            return self
    
        def __str__(self):
            return str(self.val)
    

    Running, the sequence of events is

    assign
    foo set a 0
    augmented addition
    foo get a
    baz iadd 2 2
    foo set a 2