The built-in function sum()
applied to a dictionary returns the sum of its keys:
>>> sum({1: 0, 2: 10})
3
I'd like to create a subclass of the dictionary, say SubDict
, and override some function to return the sum of its values, i.e.
>>> sum(SubDict((1, 0), (2, 10))
10
Which function do I need to override to achieve this functionality?
This is a general question, how to implement the built-in sum()
function to a class, not just in this particular case.
sum
is effectively implemented like this:
def sum(sequence, start=0):
for value in sequence:
start = start + value
return start
So, you can't override sum
directly… but if you can override the way for value in …
works on your sequence,* or the way +
works on your values, that will affect sum
automatically. Of course either one will have side effects—you'll be affecting any iteration of your sequence, or any addition of your values, not just the ones inside sum
.
To override iteration, you need to provide a __iter__
method that returns an appropriate iterator. To override addition, you need to provide a __add__
method.
But really, why are you trying to "override sum"? Why not just write a new function that does what you want? You can add code that special-cases your type(s) and then falls back to the builtin sum
otherwise. If you want to make it more "open", you can use PEP 443 single-dispatch to make it easy to register new types to be special-cased. I think that's what you really want here.
* As agf points out in the comments, despite the parameter being called sequence
, it actually takes any iterable. Which is a good thing, because dictionaries aren't sequences…
You can just do:
In [1]: sum({1:0,2:10}.values())
Out[1]: 10
If you want to implement a subclass who's sum will be the sum
of values, just override the __iter__
method:
In [21]: class MyDict(dict):
....: def __iter__(self):
....: for value in self.values():
....: yield value
....:
In [22]: d = MyDict({1:0,2:10})
In [23]: sum(d)
Out[23]: 10
But then you wont be able to do:
for key in d:
print d[key]
Because the __iter__
function will return values... You'll always have to use the keys()
function:
for key in d.keys():
print d[key]
Better solution would be to add a sum
method:
In [24]: class MyDict(dict):
....: def sum(self):
....: return sum(self.values())
....:
In [25]: d = MyDict({1:0,2:10})
In [26]: d.sum()
Out[26]: 10
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With