is is not ==¶
Level: 201 · for Python programmers
Stub — an outline, not a lesson. There is no runnable example behind this page yet, so nothing on it has been through the check that backs every other claim in this library. The bullets below are the questions the finished page has to answer.
One line: == asks two objects whether they are equal, through a method either of them may define; is asks whether they are one object, and nothing can redefine it — so x is None is the right test, two equal lists are never is, and whether int('257') is int('257') is a fact about CPython's cache rather than about the language.
What the finished page has to answer¶
- What
a == bruns:type(a).__eq__(a, b), then the reflectedtype(b).__eq__(b, a)when the first returnsNotImplemented, then the identity fallback, which is why1 == '1'isFalserather than an error while1 < '1'raises. Comparing anintwith afloatalready shows theNotImplementedstep for numbers. - What
a is bruns: nothing you can override. Defining__eq__deletes__hash__measures theNotImplementedstep for a class of your own. Two names, one object.id()as the number behind it, and why printing anid()on a page would tie the answer key to one run. - The singletons:
None,True,False,NotImplemented,Ellipsis. Whyx is Noneandx == Nonecan differ for a class with its own__eq__, and why linters insist onis. - The implementation detail people mistake for a rule: CPython keeps one object for each small integer and interns some strings, so
int('256') is int('256')isTrueandint('257') is int('257')isFalseon the same machine. Measured and dated on the page, not keyed, because it is not a promise of the language. - The warning: since 3.8,
x is 1andx is 'a'raise aSyntaxWarning, because they ask a question whose answer depends on the interpreter. - Where identity hides inside
==:in,list.indexandlist.counttestisbefore==, which is whynan in [nan]isTruewhilenan == nanisFalse. Float equality and NaN measures that case.
See also¶
- Assignment does not copy: where two names for one object come from
- Comparison has a mode: the four ways to compare two strings, none of which is
is - Float equality and NaN: identity first, inside a container
- Comparison traits ↗ in the Rust library, where equality is a trait and identity is
std::ptr::eq - Value comparisons ↗ and
is↗ in the language reference