20

If I have the code my_object = object() in Python, will my_object be equal to anything except for itself?

I suspect the answer lies in the __eq__ method of the default object returned by object(). What is the implementation of __eq__ for this default object?

EDIT: I'm using Python 2.7, but am also interested in Python 3 answers. Please clarify whether your answer applies to Python 2, 3, or both.

5
  • 3
    This is a safe and idiomatic way to create a unique sentinel value. Commented May 16, 2014 at 20:20
  • @Marcin Thanks, I asked about this because I wanted a sentinel value, but didn't want to pollute such a simple question with my use case. The question stands on it's own. Commented May 16, 2014 at 20:28
  • 2
    @Buttons840 I don't see the point of using __eq__ with a sentinel. If you want to check if something is the sentinel, python already provides the is operator which cannot be overloaded and thus it's the perfect choice for checking these kind of things. Use == only when you don't really care for identity, but for equality (and this is not generally true when using a sentinel value...) Commented May 16, 2014 at 21:28
  • @Bakuriu I wouldn't use == with a sentinel object itself, but some use cases involve implicit equality tests. I'm currently doing somelist[somelist.index(placeholderobject)] = non_placeholder_data for example, and I found this post while searching to make sure that would work on dummy objects. Commented Jun 3, 2016 at 16:13
  • Came here looking for whether using object() as sentinel is good practice. I've been using class MySentinel(): pass, but just realized that I could probably just MySentinel = object(). Thanks @Marcin and @Buttons840 for confirming my idea. Commented Sep 13, 2016 at 6:38

2 Answers 2

28

object().__eq__ returns the NotImplemented singleton:

print(object().__eq__(3))
NotImplemented

By the reflexive rules of rich comparisons, when NotImplemented is returned, the "reflected" operation is tried. So if you have an object on the RHS that returns True for that comparison, then you can get a True response even though the LHS did not implement the comparison.

class EqualToEverything(object):
    def __eq__(self,other):
        return True

ete = EqualToEverything()

ete == object() # we implemented `ete.__eq__`, so this is obviously True
Out[74]: True

object() == ete # still True due to the reflexive rules of rich comparisons
Out[75]: True

python 2 specific bit: if neither object implements __eq__, then python moves on to check if either implement __cmp__. Equivalent reflexive rules apply here.

class ComparableToEverything(object):
    def __cmp__(self,other):
        return 0

cte = ComparableToEverything()

cte == object()
Out[5]: True

object() == cte
Out[6]: True

__cmp__ is gone in python 3.

In both python 2 and 3, when we exhaust all of these comparison operators and all are NotImplemented, the final fallback is checking identity. (a is b)

Sign up to request clarification or add additional context in comments.

5 Comments

Ah, an interesting exception I hadn't thought of!
Good point, the object on the left side of == determines which eq method gets called, so order does matter.
Does the _cmp_ function returning 0 indicate they are equal, such as 3 - 3 == 0?
__cmp__ Should return a negative integer if self < other, zero if self == other, a positive integer if self > other.
One particular example where this might happen (though you'd be silly to use NumPy this way): x = object(); if x == numpy.array([x]): print('Huh?')
19

object doesn't implement __eq__, so falls back on the default comparison id(x) == id(y), i.e. are they the same object instance (x is y)?

As a new instance is created every time you call object(), my_object will never* compare equal to anything except itself.

This applies to both 2.x and 3.x:

# 3.4.0
>>> object().__eq__(object())
NotImplemented

# 2.7.6
>>> object().__eq__(object())

Traceback (most recent call last):
  File "<pyshell#60>", line 1, in <module>
    object().__eq__(object())
AttributeError: 'object' object has no attribute '__eq__'

* or rather, as roippi's answer points out, hardly ever, assuming sensible __eq__ implementations elsewhere.

1 Comment

This answer might be clearer if you replace "this will never be the case" to a explicit sentence like "In your example, my_object will only be equal to itself, and will never be equal to anything else".

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.