Skip to content

Instantly share code, notes, and snippets.

@pydemo
Last active September 7, 2018 16:53
Show Gist options
  • Save pydemo/7c6d5dd416f0beb879470966eb1d59e2 to your computer and use it in GitHub Desktop.
Save pydemo/7c6d5dd416f0beb879470966eb1d59e2 to your computer and use it in GitHub Desktop.
Comparison support in Cython

Cython extension types do not support individual comparison methods like

_eq_

_lt_

_le_

Instead Cython provides single method richcmp(x,y,op)

from cpython.object cimport Py_LT, Py_LE, Py_EQ, Py_GE, Py_GT, Py_NE

 

cdef class R:

   """Extension type that supports rich comparisons."""

   cdef double data

   def __init__(self, d):

   self.data = d

 

   def __richcmp__(x, y, int op):

   cdef:

   R r

   double data

 

   \# Make r always refer to the R instance.

   r, y = (x, y) if isinstance(x, R) else (y, x)

 

   data = r.data

   if op == Py_LT:

   return data < y

   elif op == Py_LE:

   return data <= y

   elif op == Py_EQ:

   return data == y

   elif op == Py_NE:

   return data != y

   elif op == Py_GT:

   return data > y

   elif op == Py_GE:

   return data >= y

   else:

   assert False

The integer arguments are compile time constants declared in Python runtime object.h header.

WE can access these via cimport

Test:

In [3]: r = R(10)



In [4]: r < 20 and 20 > r

Out[4]: True



In [5]: r > 20 and 20 < r

Out[5]: False



In [6]: 0 <= r <= 100

Out[6]: True

Noted that chained comparisons are supported too.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment