Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Implementing sum() for custom datatype

As I understand it, for it to be possible to cast sum() on an object, it must be an iterable, and must be "addable", i.e. it must implement methods __iter__ and __add__. However, when I do this for my class Point (just an example), this doesn't work.

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __add__(self, other):
        return Point(self.x + other.x, self.y + other.y)

    def __iter__(self):
        return self

    def __str__(self):
        return str((self.x, self.y))


print(Point(2, 2) + Point(1, 1))
>>> (3, 3)    # As expected; good!

points = [Point(0, 0), Point(2, 0), Point(0, 2), Point(2, 2)]
print(sum(points))    # Expect (4, 4)
>>> TypeError: unsupported operand type(s) for +: 'int' and 'Point'

If I implement __radd__ the same as __add__ I then get an attribute error when I try sum():

AttributeError: 'int' object has no attribute 'x'

Based on the errors my Points are somewhere being separated to just ints but I'm not sure where. Thanks for any help.

like image 773
QuantumChris Avatar asked Oct 25 '25 01:10

QuantumChris


1 Answers

This happens because sum starts with a default value of int and when doing sum(points) what really is happening is sum is first trying to add 0 + Point(0, 0) and hence the error. If you check the help on sum, this will become pretty evident,

Help on built-in function sum in module builtins:

sum(iterable, start=0, /) Return the sum of a 'start' value (default: 0) plus an iterable of numbers

When the iterable is empty, return the start value.
This function is intended specifically for use with numeric values and may
reject non-numeric types.

Change the line from,

>>> print(sum(points))

to

>>> print(sum(points, Point(0, 0)))
like image 144
han solo Avatar answered Oct 26 '25 16:10

han solo



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!