Overload Instance [key] + = val

I am writing a Java collection class intended for use with Jython. I want end users to be able to manipulate the collection as follows:

myCollection = MyJavaCollection() myCollection[0] += 10.; a = myCollection[0]; //a = 10 myCollection[0] += 20.; b = myCollection[0]; //b = 20 

In the Python documentation, I see the following methods:

  • __getitem__ and __setitem__ methods must do the job to overload the bracket statement.

  • __iadd__ method is a good candidate for += .

How can I combine both so that I want?

+5
source share
2 answers

Note that myCollection[0] += 10.; will really interpret something like:

 myCollection.__setitem__(0, myCollection.__getitem__(0).__iadd__(10.)) 

Therefore, to complete this work, you need to implement:

  • __getitem__ and __setitem__ on MyJavaCollection ; and
  • __iadd__ (or __add__ , which Python will return to if __iadd__ not implemented) to the fact that .__getitem__ will be returned, not MyJavaCollection itself - if it returns what the implementation already implements, for example, float in your example, you're fine .

Quick demo:

 >>> class Container(object): def __init__(self, contained): self.contained = contained def __getitem__(self, key): print "Container.__getitem__" return self.contained def __setitem__(self, key, val): print "Container.__setitem__" self.contained = val >>> class Contained(object): def __add__(self, other): print "Contained.__add__" return "foo" >>> test = Container(Contained()) >>> test[0] += 1 Container.__getitem__ Contained.__add__ Container.__setitem__ >>> test.contained 'foo' 
+6
source

Your original question had a list that passed as an index, so I wrote this assuming you want to access the (i, j) th element from a 2D list. You can do this by defining your class with something like:

 class MyJavaCollection: def __init__(self, values): self.values = values def __getitem__(self, indices): """ Returns the item at index (i, j) given an index list [i, j]. """ return self.values[indices[0]][indices[1]] def __setitem__(self, indices, value): """ Sets the (i, j)th item to the input value given an input index list [i, j]. """ self.values[indices[0]][indices[1]] = value 

Here you overload the __getitem__ and __setitem__ methods to retrieve or set the (i, j) th element in the values list when passing the list of indices [i, j] . If your values ​​are just numbers, then the syntax myCollection([1, 1]) += 10 will add 10 to values[1][1] .

As indicated in another answer, if you are not just storing the numbers in your object, you may need to overwrite the __add__ or __iadd__ in any class that contains your data in order to get the desired behavior.

Testing my class class:

 >> my_list = [[1, 2, 3], [4, 5, 6]] >> my_list[1][1] 5 >> my_collect = MyJavaCollection(my_list) >> my_collect[[1, 1]] 5 >> my_collect[[1, 1]] += 5 >> my_collect[[1, 1]] 10 

The documentation on special method names gives you everything you might know about special methods like this. This can be a good place to look if you don’t know which method you might need to overload.

+2
source

All Articles