classification
Title: Equality Errors when Unpickling and Pickling a Dictionary with a nan
Type: behavior Stage: resolved
Components: Versions: Python 3.8, Python 3.7
process
Status: closed Resolution: not a bug
Dependencies: Superseder:
Assigned To: Nosy List: Dennis Sweeney, rp4fx12
Priority: normal Keywords:

Created on 2021-01-30 17:36 by rp4fx12, last changed 2021-01-30 22:40 by rp4fx12. This issue is now closed.

Files
File name Uploaded Description Edit
numpy-nan-dict-error.png rp4fx12, 2021-01-30 17:36
Messages (3)
msg385990 - (view) Author: Rohan Prasad (rp4fx12) Date: 2021-01-30 17:36
Hi,

I'm having a weird issue with floats in dictionaries and equality comparison (see attached screenshot for an example). When I create two dictionaries with a nan value they pass an equivalence test. However, if I pickle and unpickle one of the dictionaries they become no longer equivalent. I would expect that the behavior would be the same irrespective of whether they are pickled/unpickled. Is there something else I should be doing here or is there a way to easily resolve this (short of writing custom ways to compare equality)?
msg385998 - (view) Author: Dennis Sweeney (Dennis Sweeney) * (Python triager) Date: 2021-01-30 21:52
I think this is the expected behavior.

It is expected by IEEE 754 that nan != nan, so that behavior exists:

>>> nan = float('nan')
>>> nan2 = float('nan')
>>> assert nan != nan2
>>> assert nan != nan

However, for "practicality beats purity" (speed) reasons, we compare containers by first checking if the entries are identical (aliases of the same object), before falling back to the actual comparisons. So identical entries make for equal containers, even if the entries don't compare equal.

>>> assert nan is nan       # quick check for identity succeeds,
>>> assert [nan] == [nan]   # therefore these compare equal

>>> assert nan is not nan2  # quick check for identity fails,
>>> assert nan != nan2      # fall back to actual comparison, which fails
>>> assert [nan] != [nan2]  # therefore these do not compare equal

When you serialize and deserialize the container with pickle, you make new entries that are no longer aliases.

From https://docs.python.org/3.9/reference/expressions.html#comparisons:
"The built-in containers typically assume identical objects are equal to themselves."
msg386001 - (view) Author: Rohan Prasad (rp4fx12) Date: 2021-01-30 22:40
I see this makes a ton of sense, thanks! I'll close this issue.
History
Date User Action Args
2021-01-30 22:40:53rp4fx12setstatus: open -> closed
resolution: not a bug
messages: + msg386001

stage: resolved
2021-01-30 21:52:40Dennis Sweeneysetnosy: + Dennis Sweeney
messages: + msg385998
2021-01-30 17:36:12rp4fx12create