From: Georg Brandl Date: Thu, 22 Oct 2009 15:00:06 +0000 (+0000) Subject: #6324: membership test tries iteration via __iter__. X-Git-Tag: v2.7a1~279 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2eee1d4df1af9bf824a9fe61bba031bf78a9cabb;p=python #6324: membership test tries iteration via __iter__. --- diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst index 6a7acf919b..3f9b181b77 100644 --- a/Doc/reference/datamodel.rst +++ b/Doc/reference/datamodel.rst @@ -1888,12 +1888,16 @@ implemented as an iteration through a sequence. However, container objects can supply the following special method with a more efficient implementation, which also does not require the object be a sequence. - .. method:: object.__contains__(self, item) - Called to implement membership test operators. Should return true if *item* is - in *self*, false otherwise. For mapping objects, this should consider the keys - of the mapping rather than the values or the key-item pairs. + Called to implement membership test operators. Should return true if *item* + is in *self*, false otherwise. For mapping objects, this should consider the + keys of the mapping rather than the values or the key-item pairs. + + For objects that don't define :meth:`__contains__`, the membership test first + tries iteration via :meth:`__iter__`, then the old sequence iteration + protocol via :meth:`__getitem__`, see :ref:`this section in the language + reference `. .. _sequence-methods: diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst index 6481894a4d..e060670302 100644 --- a/Doc/reference/expressions.rst +++ b/Doc/reference/expressions.rst @@ -1068,6 +1068,8 @@ Comparison of objects of the same type depends on the type: another one is made arbitrarily but consistently within one execution of a program. +.. _membership-test-details: + The operators :keyword:`in` and :keyword:`not in` test for collection membership. ``x in s`` evaluates to true if *x* is a member of the collection *s*, and false otherwise. ``x not in s`` returns the negation of ``x in s``. @@ -1092,7 +1094,12 @@ string, so ``"" in "abc"`` will return ``True``. For user-defined classes which define the :meth:`__contains__` method, ``x in y`` is true if and only if ``y.__contains__(x)`` is true. -For user-defined classes which do not define :meth:`__contains__` and do define +For user-defined classes which do not define :meth:`__contains__` but do define +:meth:`__iter__`, ``x in y`` is true if some value ``z`` with ``x == z`` is +produced while iterating over ``y``. If an exception is raised during the +iteration, it is as if :keyword:`in` raised that exception. + +Lastly, the old-style iteration protocol is tried: if a class defines :meth:`__getitem__`, ``x in y`` is true if and only if there is a non-negative integer index *i* such that ``x == y[i]``, and all lower integer indices do not raise :exc:`IndexError` exception. (If any other exception is raised, it is as