Python pickle: pickled objects are not equal to source objects
Asked Answered
R

2

5

I think this is expected behaviour but want to check and maybe find out why, as the research I have done has come up blank

I have a function that pulls data, creates a new instance of my custom class, then appends it to a list. The class just contains variables.

I then pickle that list to a file using protocol 2 as binary, later I re-run the script, re-pull the data from my source, I have a new list with my custom class instances, for testing I keep the data the source data the same.

Reload the pickle file

Now when I do a:

print source_list == pickle_list

this always comes back False, and I have no idea why, if I print the lists or look at the structure they look exactly the same.

Any ideas would be brill, this is my last little bit I need to sort.

Riti answered 2/3, 2012 at 8:30 Comment(0)
T
2

Comparing two objects of the same class yields False by default (unless they are the same single object), even if they have the same contents; in other words, two intuitively "identical" objects from the same class are considered different, by default. Here is an example:

>>> class C(object):
...     def __init__(self, value):
...         self.value = value
...         
>>> 
>>> C(12) == C(12)
False

You want to define __eq__() (and __ne__()) in your custom class so that it yields True for objects that contain the same data (respectively False). More information can be found in the official documentation. For the above example, this would be:

>>> class C(object):
...     # ...
...     def __eq__(self, other):
...         return self.value == other.value
...     def __ne__(self, other):
...         return not self == other  # More general than self.value != other.value
...     
>>> C(12) == C(12)  # __eq__() is called
True
>>> C(12) != C(12)  # __ne__() is called
False
Tenace answered 2/3, 2012 at 8:35 Comment(2)
Hello, thanks for the example, i missed of the ne part. good exampleRiti
You can also use dataclasses docs.python.org/3/library/dataclasses.html. They automatically implement the __eq__() for you (among other things!).Offertory
A
6

Your classes likely do not define a meaningful __eq__, and thus are being compared for object identity. Since the classes loaded from pickles are not the same objects as the ones in your generated list (even though they have the same data), you get False.

Adjoining answered 2/3, 2012 at 8:35 Comment(1)
Defining __eq__() is not sufficient. It is necessary to define __ne__() as well: if a class C only defines __eq__(), then C(12) != C(12) is True, which is not what the original poster wants.Tenace
T
2

Comparing two objects of the same class yields False by default (unless they are the same single object), even if they have the same contents; in other words, two intuitively "identical" objects from the same class are considered different, by default. Here is an example:

>>> class C(object):
...     def __init__(self, value):
...         self.value = value
...         
>>> 
>>> C(12) == C(12)
False

You want to define __eq__() (and __ne__()) in your custom class so that it yields True for objects that contain the same data (respectively False). More information can be found in the official documentation. For the above example, this would be:

>>> class C(object):
...     # ...
...     def __eq__(self, other):
...         return self.value == other.value
...     def __ne__(self, other):
...         return not self == other  # More general than self.value != other.value
...     
>>> C(12) == C(12)  # __eq__() is called
True
>>> C(12) != C(12)  # __ne__() is called
False
Tenace answered 2/3, 2012 at 8:35 Comment(2)
Hello, thanks for the example, i missed of the ne part. good exampleRiti
You can also use dataclasses docs.python.org/3/library/dataclasses.html. They automatically implement the __eq__() for you (among other things!).Offertory

© 2022 - 2024 — McMap. All rights reserved.