13

I am trying to add a class object with a number, but I'm confused on how to go about adding a class object with two numbers. For example, this is my hypothetical add class method:

class A:
    def __add__(self, b):
        return something

I know how to add this so far:

a = A()
print(a + 1)

But, what if I want to add it like this?

a = A()
print(a + 1 + 2)

Should I use *args for the add class method?

KetZoomer
  • 2,701
  • 3
  • 15
  • 43
smith1453
  • 151
  • 1
  • 1
  • 6

4 Answers4

19

No, you can't use multiple arguments. Python executes each + operator separately, the two + operators are distinct expressions.

For your example, object + 1 + 2 really is (object + 1) + 2. If (object + 1) produces an object that has an __add__ method, then Python will call that method for the second operator.

You could, for example, return another instance of A here:

>>> class A:
...     def __init__(self, val):
...         self.val = val
...     def __repr__(self):
...         return f'<A({self.val})>'
...     def __add__(self, other):
...         print(f'Summing {self} + {other}')
...         return A(self.val + other)
...
>>> A(42) + 10
Summing A(42) + 10
<A(52)>
>>> A(42) + 10 + 100
Summing A(42) + 10
Summing A(52) + 100
<A(152)>
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • 2
    Shouldn't an implemetation of __radd__ also be added here? Also, in the case of 1 + 2 + 3, is the implementation (1.__add__(2)).__add__(3) or 1.__add__(2.__add__(3))? – N M Oct 23 '17 at 09:21
  • @NM: That's not a *requirement*, not to answer the question at any rate. – Martijn Pieters Oct 23 '17 at 09:25
  • 2
    @NM: and `__radd__` is only going to be called if the LHS refused to handle the operation or if the RHS is a subclass of the LHS type. `1 + 2 + 3` is `(1).__add__(2).__add__(3)`. – Martijn Pieters Oct 23 '17 at 09:25
  • 2
    @NM: to word it differently, for `LHS + RHS`, for `not issubclass(type(RHS), type(LHS))`, `LHS.__add__(RHS)` is called first, and if that doesn't exist or returns `NotImplemented` *only then* is `RHS.__radd__(LHS)` tried. The subclass exception is there to make it possible to subclass existing types and 'capture' the operator hook. – Martijn Pieters Oct 23 '17 at 09:28
5

You would want your return value to be an object itself, that also supports the add operation, e.g.:

class A:
    def __init__(self, value=0):
        self.value = value

    def __add__(self, b):
        return A(self.value + b)

    def __str__(self):
        return str(self.value)

a = A()
print(a + 1 + 2)

Output:

3

de1
  • 2,986
  • 1
  • 15
  • 32
2

It perfectly works even with multiple values since each add only adds two values (see the multiple + signs when you ad multiple values):

class A:
    def __init__(self, value):
        self.a = value
    def __add__(self, another_value):
        return self.a + another_value


a = A(1)
print(a+1+1)
mrCarnivore
  • 4,638
  • 2
  • 12
  • 29
  • In this case the last add operation is not handled by the A class anymore but is a simple addition of 2 (returned by A.__add__) and 1. – de1 Oct 23 '17 at 09:21
  • Yes you are right, but since 1 and 2 are numbers this is what should happen. If the author wanted to add two class instances then the example would not have been a+1 but a+b (a and b being instances of A)... – mrCarnivore Oct 23 '17 at 09:22
2

you could always just do this:

>>> class A:
...     def __init__(self, val):
...         self.val = val
...     def __repr__(self):
...         return f'<A({self.val})>'
...     def __add__(self, other):
...         print(f'Summing {self} + {other}')
...         return A(self.val + other)
...
>>> A(42) + 10
Summing A(42) + 10
<A(52)>
>>> A(42) + 10 + 100
Summing A(42) + 10
Summing A(52) + 100
<A(152)>>>> class A:
...     def __init__(self, val):
...         self.val = val
...     def __repr__(self):
...         return f'<A({self.val})>'
...     def __add__(self, other):
...         print(f'Summing {self} + {other}')
...         return A(self.val + other)
...
>>> A(42) + 10
Summing A(42) + 10
<A(52)>
>>> A(42) + 10 + 100
Summing A(42) + 10
Summing A(52) + 100
<A(152)>