Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python does not consider equivalent objects to be equivalent

I am pickling, compressing, and saving python objects. I want to be able to double-check that that the object I saved is the exact same object that is returned after decompression and depickling. I thought there was an error in my code, but when I boiled the problem down to a reproducible example I found that python does not consider two seemingly identical objects created at two different points in time to be equal. Here is a reproducible example:

class fubar(object):
    pass

print(fubar() == fubar())
#False

Why does python consider these two objects to be not equal and what is the most pythonic way to check that two objects are indeed identical?

like image 982
Michael Avatar asked Dec 05 '13 00:12

Michael


People also ask

How do you equate two objects in Python?

The == operator compares the value or equality of two objects, whereas the Python is operator checks whether two variables point to the same object in memory. In the vast majority of cases, this means you should use the equality operators == and != , except when you're comparing to None .

Can objects be compared in Python?

Both “is” and “==” are used for object comparison in Python. The operator “==” compares values of two objects, while “is” checks if two objects are same (In other words two references to same object). The “==” operator does not tell us whether x1 and x2 are actually referring to the same object or not.

How do you check if two objects are the same in Python?

The is keyword is used to test if two variables refer to the same object. The test returns True if the two objects are the same object. The test returns False if they are not the same object, even if the two objects are 100% equal. Use the == operator to test if two variables are equal.

Is not vs == in Python?

In Python != is defined as not equal to operator. It returns True if operands on either side are not equal to each other, and returns False if they are equal. Whereas is not operator checks whether id() of two objects is same or not.


2 Answers

The default equality comparison in Python is to check for identity (i.e. two objects are the same object).

According to the Python Library Reference:

Non-identical instances of a class normally compare as non-equal unless the class defines the __eq__() method or the __cmp__() method.

To create your own definition of equivalence, you need to define an __eq__ method. Here is one way to do it:

class fubar(object):

    def __eq__(self, other):
        'Fubar objects are considered equal if they have the same contents'
        if type(self) != type(other):
            return NotImplemented
        return vars(self) == vars(other)

The return value of NotImplemented signals that fubar doesn't know how to make the comparison and is giving the other object a chance to do the comparison.

The Python Language Reference has this to say about NotImplemented:

This type has a single value. There is a single object with this value. This object is accessed through the built-in name NotImplemented. Numeric methods and rich comparison methods may return this value if they do not implement the operation for the operands provided. (The interpreter will then try the reflected operation, or some other fallback, depending on the operator.) Its truth value is true.

like image 136
Raymond Hettinger Avatar answered Nov 15 '22 16:11

Raymond Hettinger


They're not the same objects. Check the values of id(fubar()) and id(fubar()) for example. You need to implement your own equality method if you wish to redefine how equality works:

class fubar(object):

    def __eq__(self, other):
        return True # make this more complex

This method should return True when self and other are equal and False otherwise.

like image 28
Simeon Visser Avatar answered Nov 15 '22 17:11

Simeon Visser