## Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

### Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

# Why do comparisons work even though we do not convert "other" to an int?

In this video, we are using magic methods to compare the values of various dice.

For example, consider this method:

```def __eq__(self, other):
return int(self) == other
```

This method allows us to check whether or not two die are equal in value.

In the method, we need to convert our object to an `int` to do the comparison, but there is no such requirement for the `other` parameter. Yet, somehow, python successfully can do the comparison. The same goes for all the other comparison methods we define in this video.

My question is, how does python manage to calculate a value for `other` in order to do the comparison successfully? How does it know that it is comparing two ints, or how does it know to convert `other` to an int before converting? I am sure that this is some "magic" going on behind the scenes, but would someone be able to illuminate for me what is going on?

The video I am referring to this: https://teamtreehouse.com/library/comparing-and-combining-dice

MOD

The comparison operation is reflexive. Given, `a == b`, Python will automatically try `b == a` if needed.

If `d1` and `d2` are instances of `D6`, the flow would be:

```d1 = D6(value= 3)
d2 = D6(value= 6)

d1 == d2  # call d1.__eq__
int(d1) == d2
3 == d2  # reverse
d2 == 3  # call d2.__eq__
int(d2) == 3
6 == 3
```

This action can be seen in the code

```import random

class Die:
def __init__(self, sides=2, value=0):
print("running Die.__init__")
if not sides >= 2:
raise ValueError("Must have at least 2 sides")
if not isinstance(sides, int):
raise ValueError("Sides must be a whole number")
self.value = value or random.randint(1, sides)

def __int__(self):
print("running Die.__int__")
return self.value

class D6(Die):
def __init__(self, value=0):
print("running D6.__init__")
super().__init__(sides=6, value=value)

def __eq__(self, other):
print("running D6.__eq__", self, other)
return int(self) == other

def __ne__(self, other):
print("running D6.__ne__")
return int(self) == other

def __gt__(self, other):
print("running D6.__gt__")
return int(self) > other

def __lt__(self, other):
print("running D6.__le__")
return int(self) < other

def __ge__(self, other):
print("running D6.__ge__")
return int(self) > other or int(self) == other

def __le__(self, other):
print("running D6.__le__")
return int(self) < other or int(self) == other

return int(self) + other

print("running D6.__radd__ with int(self)", self, other)
return int(self) + other

d1 = D6(value= 3)
print('d1', d1)
d2 = D6(value= 6)
print('d2', d2)

print(d1 == d2)
```

Output:

```running D6.__init__
running Die.__init__
d1 <__main__.D6 object at 0x1163fcb38>
running D6.__init__
running Die.__init__
d2 <__main__.D6 object at 0x11640b320>
running D6.__eq__ <__main__.D6 object at 0x1163fcb38> <__main__.D6 object at 0x11640b320>
running Die.__int__
running D6.__eq__ <__main__.D6 object at 0x11640b320> 3
running Die.__int__
False
```

Update:

When an object is on the right-side of an operator a reflexive method is tried: `__radd__` instead of `__add__`

For comparison operators, there isn’t an explicit corresponding reflexive method.

From the docs

There are no swapped-argument versions of these methods (to be used when the left argument does not support the operation but the right argument does); rather, `__lt__()` and `__gt__()` are each other’s reflection, `__le__()` and `__ge__()` are each other’s reflection, and `__eq__()` and `__ne__()` are their own reflection.

So, comparing `3 > d2` would actually go

```3 > d2  # reverse
d2 < 3  # call d2.__lt__
int(d2) < 3
6 < 3
```
```running D6.__le__
running Die.__int__
```

Golly, that's more complicated than coercion! I expected that it did it the simpler way.

Okay, here is what I am understanding from this:

1) First, the object on the left is reduced to a primitive data type 2) The appropriate reflexive method for the object on the right, as defined in its own class code, is called to reduce it to a primitive data type. 3) The two primitive datatypes are compared to give the final result

Is that right?

I see from this that it tries the equation one way, goes as far as it can until it ends up with a primitive value, then flips it and goes through again until it is comparing two primitive values.

That makes sense for an easily reversible comparison, like ==, but what about < or >, where which side of the operator you are on matters?

Great! Thanks for your help, Chris!