8.6. Operator Comparison

  • a > b - will call method "gt" on object a (a.__gt__(b))

  • a >= b - will call method "ge" on object a (a.__ge__(b))

  • a < b - will call method "lt" on object a (a.__lt__(b))

  • a <= b - will call method "le" on object a (a.__le__(b))

Table 8.5. Comparison Operator Overload

Operator

Method

obj > other

obj.__gt__(other)

obj >= other

obj.__ge__(other)

obj < other

obj.__lt__(other)

obj <= other

obj.__le__(other)

8.6.1. Syntax

>>> class MyClass:
...     def __gt__(self, other): ...  # a > b
...     def __ge__(self, other): ...  # a >= b
...     def __lt__(self, other): ...  # a < b
...     def __le__(self, other): ...  # a <= b

8.6.2. Problem

>>> class Vector:
...     x: int
...     y: int
...
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
...     def __repr__(self):
...         return f'Vector(x={self.x}, y={self.y})'
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> a > b
Traceback (most recent call last):
TypeError: '>' not supported between instances of 'Vector' and 'Vector'

8.6.3. Solution

>>> class Vector:
...     x: int
...     y: int
...
...     def __init__(self, x, y):
...         self.x = x
...         self.y = y
...
...     def __repr__(self):
...         return f'Vector(x={self.x}, y={self.y})'
...
...     def __gt__(self, other):
...         a = (self.x**2 + self.y**2) ** 0.5
...         b = (other.x**2 + other.y**2) ** 0.5
...         return a > b
>>>
>>>
>>> a = Vector(x=1, y=2)
>>> b = Vector(x=3, y=4)
>>>
>>> a > b
False

8.6.4. Operator

  • operator.gt(a, b) - greater than - a > b

  • operator.ge(a, b) - greater or equal - a >= b

  • operator.lt(a, b) - less than - a < b

  • operator.le(a, b) - less or equal - a <= b

>>> import operator
>>> operator.gt(1, 2)
False
>>> operator.ge(1, 2)
False
>>> operator.lt(1, 2)
True
>>> operator.le(1, 2)
True

8.6.5. Use Case - 1

  • Game

>>> hero < Damage(20)  
>>> hero > Damage(20)  

8.6.6. Use Case - 2

>>> class User:
...     def __init__(self, uid, name):
...         self.uid = uid
...         self.name = name
...
...     def __gt__(self, other):
...         return self.uid < other.uid  # mind, that the greater uid the worse
>>>
>>>
>>> root = User(0, 'root')
>>> mark = User(1000, 'mwatney')
>>>
>>> root > mark
True

8.6.7. Use Case - 3

  • Numpy

SetUp:

>>> import numpy as np
>>> from pprint import pprint

Python does not support element-wise comparison:

>>> data = [[1, 2, 3],
...         [4, 5, 6],
...         [7, 8, 9]]
>>>
>>>
>>> data > 2
Traceback (most recent call last):
TypeError: '>' not supported between instances of 'list' and 'int'

In Python you have to iterate over each row and each element in a row, then to create a temporary row-result to which you append the information, at the end, you append this temporary object to result and process next line:

>>> data = [[1, 2, 3],
...         [4, 5, 6],
...         [7, 8, 9]]
>>>
>>> result = []
>>>
>>> for row in data:
...     tmp = []
...     for number in row:
...         tmp.append(number > 2)
...     result.append(tmp)
>>>
>>>
>>> pprint(result, width=30)
[[False, False, True],
 [True, True, True],
 [True, True, True]]

Alternatively you can use nested list comprehensions to do the same:

>>> data = [[1, 2, 3],
...         [4, 5, 6],
...         [7, 8, 9]]
>>>
>>> result = [
...     [number > 2 for number in row]
...     for row in data
... ]
>>>
>>> pprint(result, width=30)
[[False, False, True],
 [True, True, True],
 [True, True, True]]

In numpy all the comparison is being done element-wise and we do not have to worry about iteration etc. It is called vectorized operation:

>>> data = np.array([[1, 2, 3],
...                  [4, 5, 6],
...                  [7, 8, 9]])
>>>
>>> data > 2
array([[False, False,  True],
       [ True,  True,  True],
       [ True,  True,  True]])