[IronPython] in operator calls __getitem__ on class that has __len__ and __iter__ defined

Michael Foord fuzzyman at voidspace.org.uk
Thu Nov 20 17:34:18 CET 2008


Dino Viehland wrote:
> Interesting, the docs would seem to indicate our behavior is correct:
>
> For user-defined classes which do not define __contains__() and do define __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 IndexError exception. (If any other exception is raised, it is as if in raised that exception).
>
> If and only if is pretty strong language ☺  But we can start looking for __iter__ after looking for __contains__.
>   

It sounds like a doc bug then.

'in' has different meanings for mapping type containers (in refers to 
keys) and sequences (in refers to values). For a sequence 'in' naturally 
and obviously means 'is a value contained in the sequence', and passing 
the value to __getitem__ clearly gives the wrong behaviour.

For mapping types, passing the value to __getitem__ would be correct - 
unfortunately there is no way to tell the types of containers apart if 
they are pure Python classes (except in Python 2.6 where we have 
Abstract Base Classes). Explicitly implementing __contains__ is always 
better than relying on the fallback.

Michael

> From: users-bounces at lists.ironpython.com [mailto:users-bounces at lists.ironpython.com] On Behalf Of Glenn Jones
> Sent: Thursday, November 20, 2008 7:23 AM
> To: users at lists.ironpython.com
> Subject: [IronPython] in operator calls __getitem__ on class that has __len__ and __iter__ defined
>
> Yet another weirdness, but not a blocker for us:
>
> With this object:
>
> class o(object):
>   def __iter__(self):
>     print "iter"
>     return iter([1, 2, 3])
>   def __getitem__(self, index):
>     print "getitem"
>     return [1, 2, 3][index]
>   def __len__(self):
>     print "len"
>     return 3
>
> CPython:
>   
>>>> p = o()
>>>> 1 in p
>>>>         
> iter
> True
>
> IronPython 2 source drop 43741:
>   
>>>> p = o()
>>>> 1 in p
>>>>         
> getitem
> True
>
> It looks like CPython is treating it like a sequence and IronPython 2 is treating it like a dict.
>
> We have worked around this by implementing __contains__
>
> Raised as Issue 19678 on CodePlex.
>
>
> PS: How can we format code blocks on CodePlex?
>
> Glenn & Orestis
> _______________________________________________
> Users mailing list
> Users at lists.ironpython.com
> http://lists.ironpython.com/listinfo.cgi/users-ironpython.com
>   


-- 
http://www.ironpythoninaction.com/




More information about the Ironpython-users mailing list