Skip to main content

This is not the NaN you are looking for

Alternate title: "NaN - More than Not a Number"

  • Python oddities concerning NaN
  • Live demo a dict that allows use of NaN as a key the way it would be intuitively, so that all NaN values are treated as one.
  • Live demo a Counter that counts how many occurences of NaN exist

Questions

  • What about copy.copy?

Description

Have you ever wondered about float('NaN')? What it is? What you can do with it? What you shouldn't do with it? Let's take some time and explore this Not a Number and what it does (and doesn't do) in Python.

Outline

  • Introduction. 3 minutes
    • Who am I?
    • What am I going to talk about?
    • What led me to write this talk?
  • Introducing NaN. 3 minutes
    • What is NaN?
    • What purpose does NaN serve?
    • The differences beteween float('nan'), numpy.nan, and math.nan.
    • How we can tell if a "numeric" value is NaN.
  • What makes NaN so unique? 5 minutes
    • No 2 instances of NaN are the same.
    • All instances of NaN have the same repr: "nan"
    • NaN is not equal to anything, not even itself.
    • NaN can be hashed but each instance of NaN will have a different hash.
      • A set can contain multiple instances of NaN.
      • A dictionary can have multiple NaN keys, but good luck accessing the data.
      • If you have an Iterable with multiple instances of NaN and create a Counter from it, each instance will appear with a count of 1.
  • Creating a Pythonic dict that can only have one NaN. 12 minutes
    • Do a code walkthrough and live demo of a Python subclass of dict that can only have one instance of NaN.
      • Show how I created the new version of dict.
      • Simple live demo showing that we can use float('nan') as a dict key. In a regular dict it will give a KeyError when attempting to retrieve it; with the new version of dict it will work as expected.
    • Do a code walkthrough and live demo of a Python Counter class that will count how many instances of NaN are in it.
      • Show how I created a Counter class that will count all instances of NaN.
      • Live demo showing the behaviour of collections.Counter and the new Counter class.
  • Conclusion. 2 minutes
    • Quick recap of what was discussed.
    • Where to find the talk slides.
    • Where to find me.

Things I've found

>>> float('nan') ** 0
1.0
>>> float('nan') > 1
False
>>> float('nan') < 1
False
>>> float('nan') == 1
False
>>> float('nan') != 1
True
>>>> float('inf') - float('inf')
nan
>>>> f'ba{1e234567 - 1e765432}as'
'bananas'
import struct
float_bytes = b"\xaa\xbb\xcc\xdd\xff\xff\xff\xff"
val = struct.unpack("d", float_bytes)[0]
print(val)
print(struct.pack("d", val))

In a single precision floating point number (32 bit) there are 2^24 - 2 potential NaN values.

Potential improvements for NaNDict:

  • Different types of nans are distinct.
  • Perserve the original supplied nan (maybe you do and check_key() does the coalescing).
  • A dunder hook for hypothetical future other weird ass values with rogue behaviour like nan.
  • An extensive test and performance suite.
  • Accept any kind of object for the membership test.
  • Accepting unhashable values.

json parsing in Python doesn't handle NaN properly. pydis

JSON does not represent IEEE-754 floats. It does not permit NaN and infinity as part of the "number" type.

YAML does support NaN

Signed NaN and things with NaN that don't return NaN Jeff Epler post

From Jeff Epler - NaN Cipher

[math.nan] == [math.nan] is True. Identity check on the objects before equality check Issue raised on Python 3.0 about this behaviour

Prior to Python 3.11 CPython did not require IEEE-754 support and included a Py_NO_NAN macro. Current versions of CPython require IEEE-754 support and the macro was removed.

Quotes

NaN is a lot like infinity in that people want to treat it as a number but It's Not and trying to do that will only lead to surprise and disappointment. - Luna Celeste

NaN is a wild land governed by laws both alien and arcane - Luna Celeste

References

https://xkcd.com/851/

https://brassnet.biz/blog/nan-is-weird.html

https://github.com/python/cpython/issues/87641

https://twit.social/@brass75/116168712645625711

https://discuss.python.org/t/question-about-float-nan/106378

https://en.wikipedia.org/wiki/NaN

Release files for nandict 2026.7.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for nandict 2026.7.3
File Size Uploaded
nandict-2026.7.3.tar.gz 4.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for nandict 2026.7.3
File Interpreter ABI Platform
nandict-2026.7.3-py3-none-any.whl Python 3 none any Details

Total release size: 11.2 kB

Release files / nandict-2026.7.3.tar.gz

Download URL nandict-2026.7.3.tar.gz
Size 4.9 kB
Tags Source
SHA-256 checksum
How to use checksums
a4302ef849829c171d149a532e53f0da72d95a0903e2408cd72ade7115e8fd7f
BLAKE2b-256 checksum
How to use checksums
0cc3a35b680459543f77a4d3726d3b37f68dab0c8942de1305b0f8acaf1c6d6f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release files / nandict-2026.7.3-py3-none-any.whl

Download URL nandict-2026.7.3-py3-none-any.whl
Size 6.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e8cef2093f9d0fa95186562509a6769bb5eadb4b4450de0cb4035caac4d740dd
BLAKE2b-256 checksum
How to use checksums
80e25f42b73b8d9923269c8d4d039e76679b52a4a39e55719fc0adc8c7230388
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.13

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Jul 25, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

2026.7.3 This release

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page