Skip to content

Membership test documentation doesn't account for hashing in sets/dicts #150165

@KRRT7

Description

@KRRT7

As discussed on discuss.python.org.

Problem

The membership test equivalence in §6.10.2 has two issues:

1. Ignores hashing for sets/dicts. It says x in y for sets is equivalent to any(x is e or x == e for e in y) — a linear scan. Sets and dicts use hash lookup, so this equivalence is false when the hash invariant is violated (a == b but hash(a) != hash(b)). This was previously reported as bpo-45832 / #89990.

2. Observable identity check. The x is e short-circuit means membership can succeed via identity when equality fails (e.g., NaN). But the spec says nothing about whether repeated evaluations of non-literal expressions produce the same object, so this behavior is implementation-dependent.

Concrete example

Nuitka/Nuitka#3889 — Nuitka's constant blob cached float('nan') as a singleton, making nan2 in {nan1} return True instead of False. Both behaviors are spec-compliant because the spec doesn't address call identity. This is what motivated the fix.

Prior art / related issues

Proposed fix

Branch: clarify-membership-docs on KRRT7/cpython.

  • Split the equivalence in §6.10.2: sequence types (linear scan) vs hash-based containers (hash lookup)
  • Add a note acknowledging edge cases (NaN, mutable __eq__)
  • Add a clarifying sentence to §6.2.3.1 that non-literals make no identity guarantees

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions