Ivan Semochkin
Ivan Semochkin

Reputation: 8907

How int() object uses "==" operator without __eq__() method in python2?

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

Upvotes: 15

Views: 1334

Answers (3)

Ismael Harun
Ismael Harun

Reputation: 147

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

Upvotes: 0

Blender
Blender

Reputation: 298430

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

Upvotes: 10

Jesse Shapiro
Jesse Shapiro

Reputation: 149

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

Upvotes: 6

Related Questions