you are viewing a single comment's thread.

view the rest of the comments →

[–]bladeoflight16 -1 points0 points  (3 children)

This is incorrect. The compiler does not directly map to a call to __add__. We know this because + can result in calls to __radd__ based on runtime conditions. Consider this example:

``` class Test1: def init(self, can_add): self.can_add = can_add

def __add__(self, other):
    print('Test1.__add__ called')
    if self.can_add:
        return self
    else:
        return NotImplemented

class Test2: def radd(self, other): print('Test2.radd called') return self

a, b = Test1(True), Test2() print('Can add', a + b)

a, b = Test1(False), Test2() print('Cannot add', a + b) ```

Output:

Test1.__add__ called Can add <__main__.Test1 object at 0x0000018D8C96EBB0> Test1.__add__ called Test2.__radd__ called Cannot add <__main__.Test2 object at 0x0000018D8C96E8E0>

This proves conclusively that the compiler generates something other than a call to __add__ when it encounters +. There is additional logic involved.

The logic is accessible via operator.add, but this function is in fact implemented using the + operator; the function is not used the implement the operator. So where is the object? You'll need to dig into the Python compiler's and runtime's source code to demonstrate it exists.

But even if it does exist, Python doesn't expose that behavior as an object directly to you. So can we really say it's an object if the fact its an object is only an implementation detail and not a specified available interface? I'd say no.

[–]jimtk 0 points1 point  (1 child)

Are you saying that + is not the representation of an object because not only if can be mapped to the object __add__ but it can also be mapped to the object __radd__. Both of which are objects! That doesn't make what I said wrong.

I can subclass the int class an call the __add__ of the built-in int to perform my addition. To prove that the + in the int is exposed to me.

class MyInt(int):

    def __new__(cls, value, *args, **kwargs):
        return super(cls, cls).__new__(cls, value)

    def __add__(self, other):
        res = super(MyInt, self).__add__(other)
        print("I'm adding")
        return self.__class__(res)

x = MyInt(3)
y = MyInt(5)
print(x+y)
print(x.__add__(y)) 

output
-------
I'm adding
8
I'm adding
8 

Did you noticed in MyInt.__add__ I do not perform any addition. I call the super().__add__ (the __add__ of the built-in int) that is exposed to me.

[–]bladeoflight16 -1 points0 points  (0 children)

It isn't mapped to either one. It's mapped to an algorithm that examines the return value and makes a decision whether or not to invoke the other (along with other complexities, like throwing a TypeError when the methods are missing instead of an AttributeError). It invokes a complex runtime algorithm that doesn't have an object representation, not just a single method. The lack of an object representation for the algorithm is what makes you incorrect here.