Designing class with __add__
operator overloading - Difference between __add__() and add() inside the class definition in Python - Stack Overflow
class - Using __add__ operator with multiple arguments in Python - Stack Overflow
How to overload __add__ method in a self made class to sum multiple objects of the class?
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)>
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
I can't wrap my mind around how this code works.
class Color:
def __init__(self, red, blue, green):
self.red = red
self.blue = blue
self.green = green
def __repr__(self):
return "Color with RGB = ({red}, {blue}, {green})".format(red=self.red, blue=self.blue, green=self.green)
def __add__(self, other):
new_red = min(self.red + other.red, 255)
new_blue = min(self.blue + other.blue, 255)
new_green = min(self.green + other.green, 255)
return Color(new_red, new_blue, new_green)
red = Color(255, 0, 0)
blue = Color(0, 255, 0)
green = Color(0, 0, 255)
magenta = red + blue
cyan = blue + green
yellow = red + green
white = red + blue + green
print(magenta, cyan, yellow, white, sep="\n")
The main confusion stems from the __add__ method and everything below it. What exactly are the variables below it assigned?
I assume that the argument for other is provided by adding a second object to the first object such as magenta = red + blue but I don't really get how the method finds other.blue blue between 3 different variables. Or does it create all 3 variables when __add__ is used, return them all but only other.blue results in 255? But the other two do not return 255, so it's not really a default value and seems to only be assigned if self.red and other.blue are both more than 0?
According to print(help(min)) :
With a single iterable argument, return its smallest item. The default keyword-only argument specifies an object to return if the provided iterable is empty. With two or more arguments, return the smallest argument.
But in this case, there are two arguments - neither of which have a comparable value (unless you count alphabetical order), and a default number of 255 which isn't even an object? So what exactly does the min() function do in this code?
And how does white = red + blue + green work? There are 3 arguments and __add__ only accepts two. Or does it add the first two together and save it in some kind of temporary memory while adding green to it?
I've never been more lost.
A method called add is just that - a method with that name. It has no special meaning whatsoever to the language or the interpreter. The only other thing that could be said about it is that sets have a method with the same name. That's it, nothing special about it.
The method __add__ is called internally by the + operator, so it gets special attention in the language spec and by the interpreter and you override it to define addition for object of a class. You don't call it directly (you can - they're still normal methods, they only get called implicitly in some circumstances and have some extra restrictions - but there's rarely if ever a reason - let alone a good reason). See the docs on "special" methods for details and a complete list of other "special" methods.
If you just went through this doc https://docs.python.org/3/library/operator.html and was curious about the differences between e.g.
operator.add(a, b)
operator.__add__(a, b)
Check the source code https://github.com/python/cpython/blob/3.10/Lib/operator.py :
def add(a, b):
"Same as a + b."
return a + b
...
# All of these "__func__ = func" assignments have to happen after importing
# from _operator to make sure they're set to the right function
...
__add__ = add
So
print(3 + 3) # call 'operator.__add__' which is `operator.add`
import operator
print(operator.add(3, 3)) # call 'operator.add' directly
Is there any reason why list uses append() and set uses add() function?* For me both append() and add() does the same thing, adds an element to the list of set. Why different method names were chosen?
* not function, but method
Python parser is intentionally kept dumb and simple. When it sees 1., it thinks you are midway through a floating point number, and 1._ is not a valid number (or more correctly, 1. is a valid float, and you can't follow a value by _: "a" __add__("b") is also an error). Thus, anything that makes it clear that . is not a part of the number helps: having a space before the dot, as you discovered (since space is not found in numbers, Python abandons the idea of a float and goes with integral syntax). Parentheses would also help: (1).__add__(2). Adding another dot does as well: 1..__add__(2) (here, 1. is a valid number, then .__add__ does the usual thing).
The python lexical parser tries to interpret an integer followed by a dot as a floating point number. To avoid this ambiguity, you have to add an extra space.
For comparison, the same code works without problem on a double:
>>> 4.23.__add__(2)
6.23
It also works if you put the int in parentheses:
>>> (5).__add__(4)
9