15

Recently I read the "Fluent python" and understood how == operator works with python objects, using __eq__() method. But how it works with int instances in python2?

>>> a = 1
>>> b = 1
>>> a == b
True
>>> a.__eq__(b)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'

in python3 all a.__eq__(b) returns True

3
  • 1
    stackoverflow.com/questions/3588776/… look at a few answers here, i think they explain it well Commented Apr 28, 2016 at 17:31
  • 1
    Wild guess, but from operator import eq; eq(2,2) does work in Python2. Either that or using __cmp__ Commented Apr 28, 2016 at 17:33
  • 1
    a.__cmp__ exists, which might be what Python 2 is using. Commented Apr 28, 2016 at 17:33

3 Answers 3

10

Python prefers to use rich comparison functions (__eq__, __lt__, __ne__, etc.), but if those don't exist, it falls back to using a single comparison function (__cmp__, removed in Python 3):

These are the so-called “rich comparison” methods, and are called for comparison operators in preference to __cmp__() below.

The Python 2 integer type doesn't implement a rich comparison function:

PyTypeObject PyInt_Type = {
    ...
    (cmpfunc)int_compare,                       /* tp_compare */
    ...
    0,                                          /* tp_richcompare */

In Python 3, the integer type (now a long) implements only a rich comparison function, since Python 3 dropped support for __cmp__:

PyTypeObject PyLong_Type = {
    ...
    long_richcompare,                           /* tp_richcompare */

This is why (123).__eq__ doesn't exist. Instead, Python 2 falls back to (123).__cmp__ when testing the equality of two integers:

>>> (1).__eq__(2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'int' object has no attribute '__eq__'
>>> (1).__cmp__(2)
-1
Sign up to request clarification or add additional context in comments.

Comments

6

In Python 2, the int object uses the __cmp__() method instead of the rich methods like __eq__(), __lt__(), __gt__(), and others.

2 Comments

How do you know this? Do you have a reference in the documentation, or ... ?
You can check this by running dir(int_instance) in Python; there's no __eq__ method available. You can read more about __cmp__() versus the rich operators here.
0

Here's my answer.

import sys
SPECIAL_OPNAMES = \
    { '__eq__': (lambda *args, **kwargs: not cmp(*args, **kwargs)) \
    , '__ne__': (lambda *args, **kwargs: cmp(*args, **kwargs)) \
    , '__lt__': (lambda *args, **kwargs: cmp(*args, **kwargs) < 0) \
    , '__ge__': (lambda *args, **kwargs: cmp(*args, **kwargs) >= 0) \
    , '__gt__': (lambda *args, **kwargs: cmp(*args, **kwargs) > 0) \
    , '__le__': (lambda *args, **kwargs: cmp(*args, **kwargs) <= 0) \
    } if sys.version_info.major == 2 else \
    {}

Working example:

>>> item = 1
>>> opname = '__eq__'
>>> t = type(item)
>>> op = SPECIAL_OPNAMES[opname] if opname in SPECIAL_OPNAMES else getattr(t, opname)
>>> op(item, 1)
True

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.