diff options
author | Raymond Hettinger <rhettinger@users.noreply.github.com> | 2021-04-04 02:54:49 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-04 02:54:49 (GMT) |
commit | f8775e4f72240faba3947eea8efdd83ee56ae1fd (patch) | |
tree | efc37102dd4ecb53d16200b2b164e896bf403b68 /Doc | |
parent | 35715d1e72b7e15e337087863c75af447199e0fb (diff) | |
download | cpython-f8775e4f72240faba3947eea8efdd83ee56ae1fd.zip cpython-f8775e4f72240faba3947eea8efdd83ee56ae1fd.tar.gz cpython-f8775e4f72240faba3947eea8efdd83ee56ae1fd.tar.bz2 |
bpo-43325: Add FAQ entry for identity tests (GH-25168)
Diffstat (limited to 'Doc')
-rw-r--r-- | Doc/faq/programming.rst | 87 | ||||
-rw-r--r-- | Doc/tutorial/datastructures.rst | 5 |
2 files changed, 89 insertions, 3 deletions
diff --git a/Doc/faq/programming.rst b/Doc/faq/programming.rst index b75c60a..93ffd36 100644 --- a/Doc/faq/programming.rst +++ b/Doc/faq/programming.rst @@ -1701,6 +1701,93 @@ to the object: 13891296 +When can I rely on identity tests with the *is* operator? +--------------------------------------------------------- + +The ``is`` operator tests for object identity. The test ``a is b`` is +equivalent to ``id(a) == id(b)``. + +The most important property of an identity test is that an object is always +identical to itself, ``a is a`` always returns ``True``. Identity tests are +usually faster than equality tests. And unlike equality tests, identity tests +are guaranteed to return a boolean ``True`` or ``False``. + +However, identity tests can *only* be substituted for equality tests when +object identity is assured. Generally, there are three circumstances where +identity is guaranteed: + +1) Assignments create new names but do not change object identity. After the +assignment ``new = old``, it is guaranteed that ``new is old``. + +2) Putting an object in a container that stores object references does not +change object identity. After the list assignment ``s[0] = x``, it is +guaranteed that ``s[0] is x``. + +3) If an object is a singleton, it means that only one instance of that object +can exist. After the assignments ``a = None`` and ``b = None``, it is +guaranteed that ``a is b`` because ``None`` is a singleton. + +In most other circumstances, identity tests are inadvisable and equality tests +are preferred. In particular, identity tests should not be used to check +constants such as :class:`int` and :class:`str` which aren't guaranteed to be +singletons:: + + >>> a = 1000 + >>> b = 500 + >>> c = b + 500 + >>> a is c + False + + >>> a = 'Python' + >>> b = 'Py' + >>> c = b + 'thon' + >>> a is c + False + +Likewise, new instances of mutable containers are never identical:: + + >>> a = [] + >>> b = [] + >>> a is b + False + +In the standard library code, you will see several common patterns for +correctly using identity tests: + +1) As recommended by :pep:`8`, an identity test is the preferred way to check +for ``None``. This reads like plain English in code and avoids confusion with +other objects that may have boolean values that evaluate to false. + +2) Detecting optional arguments can be tricky when ``None`` is a valid input +value. In those situations, you can create an singleton sentinel object +guaranteed to be distinct from other objects. For example, here is how +to implement a method that behaves like :meth:`dict.pop`:: + + _sentinel = object() + + def pop(self, key, default=_sentinel): + if key in self: + value = self[key] + del self[key] + return value + if default is _sentinel: + raise KeyError(key) + return default + +3) Container implementations sometimes need to augment equality tests with +identity tests. This prevents the code from being confused by objects such as +``float('NaN')`` that are not equal to themselves. + +For example, here is the implementation of +:meth:`collections.abc.Sequence.__contains__`:: + + def __contains__(self, value): + for v in self: + if v is value or v == value: + return True + return False + + Modules ======= diff --git a/Doc/tutorial/datastructures.rst b/Doc/tutorial/datastructures.rst index 5c6b65f..e42b380 100644 --- a/Doc/tutorial/datastructures.rst +++ b/Doc/tutorial/datastructures.rst @@ -661,9 +661,8 @@ operators, not just comparisons. The comparison operators ``in`` and ``not in`` check whether a value occurs (does not occur) in a sequence. The operators ``is`` and ``is not`` compare -whether two objects are really the same object; this only matters for mutable -objects like lists. All comparison operators have the same priority, which is -lower than that of all numerical operators. +whether two objects are really the same object. All comparison operators have +the same priority, which is lower than that of all numerical operators. Comparisons can be chained. For example, ``a < b == c`` tests whether ``a`` is less than ``b`` and moreover ``b`` equals ``c``. |