oeter
oeter

Reputation: 812

Comparison operator "==" for value equality or reference equality?

So many tutorials have stated that the == comparison operator is for value equality, like in this answer, quote:

  • == is for value equality. Use it when you would like to know if two objects have the same value.
  • is is for reference equality. Use it when you would like to know if two references refer to the same object.

However, I found that the Python doc says that:

x==y calls x.__eq__(y). By default, object implements __eq__() by using is, returning NotImplemented in the case of a false comparison: True if x is y else NotImplemented."

It seems the default behavior of the == operator is to compare the reference quality like the is operator, which contradicts what these tutorials say.

So what exactly should I use == for? value equality or reference equality? Or it just depends on how you implement the __eq__ method.


I think the doc of Value comparisons has illustrated this question clearly:

The operators <, >, ==, >=, <=, and != compare the values of two objects. The value of an object is a rather abstract notion in Python. Comparison operators implement a particular notion of what the value of an object is. One can think of them as defining the value of an object indirectly, by means of their comparison implementation.

The behavior of the default equality comparison, that instances with different identities are always unequal, may be in contrast to what types will need that have a sensible definition of object value and value-based equality. Such types will need to customize their comparison behavior, and in fact, a number of built-in types have done that.

The default behavior for equality comparison (== and !=) is based on the identity of the objects. Hence, equality comparison of instances with the same identity results in equality, and equality comparison of instances with different identities results in inequality. A motivation for this default behavior is the desire that all objects should be reflexive (i.e. x is y implies x == y).

It also includes a list that describes the comparison behavior of the most important built-in types like numbers, strings and sequences, etc.

Upvotes: 5

Views: 4336

Answers (4)

Daniel Hepper
Daniel Hepper

Reputation: 29967

object implements __eq__() by using is, but many classes in the standard library implement __eq__() using value equality. E.g.:

>>> l1 = [1, 2, 3]
>>> l2 = [1, 2, 3]
>>> l3 = l1
>>> l1 is l2
False
>>> l1 == l2
True
>>> l1 is l3
True

In your own classes, you can implement __eq__() as it makes sense, e.g.:

class Point():
    def __init__(self, x, y):
        self.x = x
        self.y = y
    def __eq__(self, other):
        return self.x == other.x and self.y == other.x

Upvotes: 4

blek__
blek__

Reputation: 120

one = 1
a = one
b = one
if (a == b): # this if works like this: if (1 == 1)
if (a is 1): # this if works like this: if (int.object(1, memory_location:somewhere) == int.object(1, memory_location:variable.one))

thus, a is 1 won't work because its arguments are not pointing to the same location.

Upvotes: -1

timgeb
timgeb

Reputation: 78680

It solely depends on what __eq__ does. The default __eq__ of type object behaves like is. Some builtin datatypes use their own implementation. For example, two lists are equal if all their values are equal. You just have to know this.

Upvotes: 3

Tamil Selvan
Tamil Selvan

Reputation: 1749

To add your thought process with a simple definition ,

The Equality operator == compares the values of both the operands and checks for value equality. Whereas the is operator checks whether both the operands refer to the same object or not (present in the same memory location).

In a nutshell, is checks whether two references point to the same object or not.== checks whether two objects have the same value or not.

For example:

a=[1,2,3]
b=a        #a and b point to the same object
c=list(a)  #c points to different object 

if a==b:
    print('#')   #output:#
if a is b:
    print('##')  #output:## 
if a==c:
    print('###') #output:## 
if a is c:
    print('####') #no output as c and a point to different object 

Upvotes: 0

Related Questions