[Python-Dev] misbehaving __contains__

tomer filiba tomerfiliba at gmail.com
Tue Jan 22 20:26:59 CET 2008


i'm using python to create expression objects, for more intuitive
usage as
predicates, for instance:
    x = (Arg(0) > 17) & (Arg(1).foo == "bar")
instead of
    x = And(Gt(Arg(0), 17), Eq(GetAttr(Arg(1), "foo"), "bar"))

so now i can use x.eval(18, "spam") and get the result of the
expression.

i'm doing it by overriding all the operators to return expression
objects,
instead of evaluating the result immediately. it works fine, but i
encountered
a problem with making __contains__ behave so.

it turns out __contains__ coerces the return value into a bool. this
might
seem logical at first, but is not consistent with the result of the
language.

consider the following code:

>>> class Foo(object):
...     def __contains__(self, key):
...             return 17
...     def __eq__(self, other):
...             return 19
...
>>>
>>> f=Foo()
>>> f == 8
19
>>> 8 in f
True

as you can see, __eq__ does not coerces the result to bool, so why
should
__contains__ do that?

i've looked at PySequence_Contains in objects/abstract.c, but i can't
quite
understand where the coercion is made. is because the function is
typed
as int? if so, i believe it should either be changed to PyObject, or
have
cmp_outcome (in ceval.c) not use this API directly, and rather return
the
result as it is returned from __contains__.

i see no reason it should behave differently than __eq__ and the rest
of comparison operators.


-tomer


More information about the Python-Dev mailing list