http://hg.python.org/cpython/file/db9fe49069ed/Python/ceval.c#l4545)">

(original) (raw)

Oh, just to show what I mean here with some code (same in both Python 2.x and 3.x):

-----
from \_\_future\_\_ import print\_function

class C(object):
� � def \_\_contains\_\_(self, x):
� � � � print('\_\_contains\_\_({0!r})'.format(x))
� � � � return x

� � def \_\_lt\_\_(self, x):
� � � � print('\_\_lt\_\_({0!r})'.format(x))
� � � � return x

c = C()
print(42 in c)
print(0 in c)
print(c < 42)
print(c < 0)
-----

This prints the following:

\_\_contains\_\_(42)
True
\_\_contains\_\_(0)
False
\_\_lt\_\_(42)
42
\_\_lt\_\_(0)
0

Whereas I'd kinda expect it to print:

\_\_contains\_\_(42)
42
\_\_contains\_\_(0)
0
\_\_lt\_\_(42)
42
\_\_lt\_\_(0)
0

-Ben



On Mon, Jul 15, 2013 at 12:21 PM, Ben Hoyt <benhoyt@gmail.com> wrote:
I'm curious why the return value of \_\_contains\_\_ is coerced to True or False, whereas the return value of "normal" comparison operators like \_\_lt\_\_ and the like are not. The latter return the value directly without forcing it to be True or False.�


This makes overriding __contains__ significantly less flexible, so I'm wondering why it's designed or implemented that way. (I believe it's the cmp_outcome() function in Python/ceval.c that does this:�http://hg.python.org/cpython/file/db9fe49069ed/Python/ceval.c#l4545)


For example, the "peewee" ORM overloads \_\_lt\_\_ and the like so it can map Python expressions to SQL. But it can't do this with the "in" operator due to the result of "x in y" always returning True or False in Python. So it (ab)uses the "<<" operator to do this instead (See the peewee docs at�http://peewee.readthedocs.org/en/latest/peewee/querying.html#column-lookups).

I'm sure there's a good reason for why "in" is different here, but I can't see why right now.

-Ben