[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