[pypy-issue] Issue #2352: list.__contains__ compares objects in wrong order (pypy/pypy)

Vasiliy Faronov issues-reply at bitbucket.org
Sat Jul 23 07:37:06 EDT 2016


New issue 2352: list.__contains__ compares objects in wrong order
https://bitbucket.org/pypy/pypy/issues/2352/list__contains__-compares-objects-in-wrong

Vasiliy Faronov:

Consider the following program:

```
#!python
class Foo(object):

    def __init__(self, bar):
        self.bar = bar

    def __repr__(self):
        return 'Foo(%r)' % (self.bar,)

    def __eq__(self, other):
        print('Foo.__eq__(%r, %r)' % (self, other))
        return self.bar == other

foo1 = Foo('A')
foo2 = Foo('B')
assert foo1 not in [foo2]
```

Under CPython 2.7.11 and 3.5.1, it prints:

```
#!python
Foo.__eq__(Foo('A'), Foo('B'))
Foo.__eq__(Foo('B'), 'A')
```

But under PyPy 5.3.1 (2.7), it prints:

```
#!python
Foo.__eq__(Foo('B'), Foo('A'))
Foo.__eq__(Foo('A'), 'B')
```

PyPy’s behavior contradicts the [Python 2 language reference](https://docs.python.org/2/reference/expressions.html#membership-test-details):

> For the list and tuple types, `x in y` is true if and only if there exists an index *i* such that either `x is y[i]` or `x == y[i]` is true.

According to the [Python 3 language reference](https://docs.python.org/3/reference/expressions.html#value-comparisons) (can’t find anything about this in Python 2), equality does not have to be symmetric (emphasis mine):

> User-defined classes that customize their comparison behavior should follow some consistency rules, **if possible**:
>
> . . .
>
> * Comparison should be symmetric
>
> . . .
>
> Python does not enforce these consistency rules. In fact, the not-a-number values are an example for not following these rules.

In my case, `x` and `y` are instances of different classes with completely different, magical `__eq__`, so this becomes important.




More information about the pypy-issue mailing list