[Python-3000] Fwd: [Python-Dev] misbehaving __contains__

tomer filiba tomerfiliba at gmail.com
Tue Jan 22 21:36:11 CET 2008

i can work on a patch, but before i start, i want to make sure it's
accepted. the change will require sq_contains to return a PyObject,
as well as some minor tweaks to cmp_outcome().


---------- Forwarded message ----------
From: Guido van Rossum <guido at python.org>
Date: Jan 22, 2008 9:55 PM
Subject: Re: [Python-Dev] misbehaving __contains__
To: tomer filiba <tomerfiliba at gmail.com>
Cc: python-dev at python.org

The issue is that the sq_contains slot is defined as returning an int,
while the tp_richcompare slot is defined as returning a PyObject *.

Your first opportunity for changing this will be Py3k. Please submit a patch!

On Jan 22, 2008 11:26 AM, tomer filiba <tomerfiliba at gmail.com> wrote:
> 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 rest 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

--Guido van Rossum (home page: http://www.python.org/~guido/)

More information about the Python-3000 mailing list