newbie Q: sequence membership

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Sat Nov 17 09:40:55 CET 2007


En Sat, 17 Nov 2007 04:02:12 -0300, saccade <trivik at gmail.com> escribió:

>>>> a, b = [], []
>>>> a.append(b)
>>>> b.append(a)
>>>> b in a
> True
>>>> a in a
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> RuntimeError: maximum recursion depth exceeded in cmp
>>>>
>>>> a is a[0]
> False
>>>> a == a[0]
> Traceback (most recent call last):
>   File "<stdin>", line 1, in <module>
> RuntimeError: maximum recursion depth exceeded in cmp
>
> ----------
>
> I'm a little new to this language so my mental model on whats going on
> may need to be refined.
>
> I expect "a in a" to evaluate to "False". Since it does not it may be
> that while checking equality it uses "==" and not "is".

Exactly. Testing for equality appears to be the most wanted behavior, so  
the language designers have chosen it.

> If that is the
> reason then  the question becomes why doesn't "a == a[0]" evaluate to
> "False"?

The 'in' operator does something like this:

def __contains__(self, other):
     for item in self:
         if item==other:
             return True
     return False

(that is, a sequential scan). Note that it uses == to test for membership  
(as you can read on http://docs.python.org/lib/typesseq.html). The '=='  
operator for lists first compares their length, and being equal, then  
compares their elements. In the 'a==b' case, both a and b have length 1,  
so the next step is to compare a[0] (that is, b) with b[0] (that is, a).  
Now we have to test b==a, which does the same thing again and again...  
until the recursion limit is reached.

> As a side, and if that is the reason, is there a version of
> "in" that uses "is"? "a is in a" does not work.

You can write your own membership test based on identity ('is'):

def contains_by_identity(container, other):
     return any(other is item for item in container)

-- 
Gabriel Genellina




More information about the Python-list mailing list