[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Why does __ne__ exist?

On Mon, Jan 8, 2018 at 9:32 AM, bartc <bc at freeuk.com> wrote:
> On 07/01/2018 21:51, Chris Angelico wrote:
>>>>>>> dis.dis("not (x in y)")
>>>>     1           0 LOAD_NAME                0 (x)
>>>>                 2 LOAD_NAME                1 (y)
>>>>                 4 COMPARE_OP               7 (not in)
>>> I get '4 COMPARE OP    6 (in)' here. So they are distinct ops. 'not in'
>>> doesn't just call 'in', then apply 'not'. Not here anyway.
>> The fact that your Python doesn't optimize it is actually beside the
>> point; if _any_ Python interpreter can optimize this down, it must be
>> semantically identical.
> Actually I didn't see the 'not' on the outside of the brackets. I thought
> the two expressions were 'not in' and 'in' and that you might have
> transcribed the '7 (not in)' part wrongly.

That's why I don't transcribe - I copy and paste. It's way WAY safer that way.

> But this reduction isn't necessarily an optimisation. It might just be a
> syntactical transformation from 'not (a in b)' to '(a not in b)'
> The disassembly for 'in' and 'not in' suggests that these are two
> independent operators, which could indeed have behaviours that are not
> complements of each other.

Uhm, if the peephole optimizer does a syntactical transformation, it
MUST retain the semantics. The disassembly for "in" and "not in" shows
that they are independent, but the disassembly for "not (x in y)"
proves that they are semantically linked.

> On the other hand, when you /did/ want to evaluate 'in' followed by 'not',
> then you want:
>    not (a in b)            # compare using 'not in'
> to do the same thing as:
>    temp = a in b           # compare using 'in'
>    not temp                # apply unary not
> Then there might not be the freedom to have in/not in have independent
> behaviours.

And the whole point of my post is that there is no such freedom - that
"not in" MUST always give the exact converse of "in". (And if
__contains__ returns something other than a boolean, it is coerced
before the operator returns it.) Yet equality is not like that. Hence
my post.