Differences of "!=" operator behavior in python3 and python2 [ bug? ]

M

Mr. Joe

I seem to stumble upon a situation where "!=" operator misbehaves in
python2.x. Not sure if it's my misunderstanding or a bug in python
implementation. Here's a demo code to reproduce the behavior -
"""
# -*- coding: utf-8 -*-
from __future__ import unicode_literals, print_function

class DemoClass(object):
def __init__(self, val):
self.val = val

def __eq__(self, other):
return self.val == other.val

x = DemoClass('a')
y = DemoClass('a')

print("x == y: {0}".format(x == y))
print("x != y: {0}".format(x != y))
print("not x == y: {0}".format(not x == y))
"""

In python3, the output is as expected:
"""
x == y: True
x != y: False
not x == y: False
"""

In python2.7.3, the output is:
"""
x == y: True
x != y: True
not x == y: False
"""
Which is not correct!!

Thanks in advance for clarifications.
Regards,
TB
 
F

Fábio Santos

this looks to me like an issue with operator precidence

you code is evaluating as (Not x) == y
rather than not (x == y)

I can say for sure that the precedence is as expected. I always use "not
.... == ..." Instead of !=.
 
N

Ned Batchelder

I can say for sure that the precedence is as expected. I always use
"not ... == ..." Instead of !=.

If you don't mind my asking, why do you do that?

--Ned.
 
F

Fábio Santos

I think it is more readable. When doing more complicated statements I use
!= instead, but when it's a single test I prefer not … ==

It's a personal thing. It may also have to do with the fact that I didn't
know python had != when I was a novice.
 
F

Fábio Santos

I would then still write it as not (x == y) to make it clear to myself &
avoid any possible confusion although I think that X != Y is much
cleaner.
2 lines from the zen stand out here:-

Explicit is better than implicit.
in the face of ambiguity refuse the temptation to guess.

And here I was, thinking I was being pythonic. I hope other people
using my code will be able to understand it well, not just myself, so
using the most common idioms should be the best way to go.
 
M

Mark Lawrence

I would then still write it as not (x == y) to make it clear to myself &
avoid any possible confusion although I think that X != Y is much
cleaner.
2 lines from the zen stand out here:-

Explicit is better than implicit.
in the face of ambiguity refuse the temptation to guess.

there are many features of Python (& other languages) i did not now when
I started but have adopted once I understood what they were & how they
worked. then again use what you are most comfortable with.

Practicality beats purity

I much prefer the alternative <> for != but some silly people insisted
that this be removed from Python3. Just how stupid can you get?
 
D

Dave Angel

I much prefer the alternative <> for != but some silly people insisted
that this be removed from Python3. Just how stupid can you get?

So which special methods should the <> operator call? By rights it
ought to call both __gt__ and __lt__ and return True if either of them
is True.
 
A

Andrew Berg

I much prefer the alternative <> for != but some silly people insisted
that this be removed from Python3.
It's not removed from Python 3, though:

Python 3.3.1 (v3.3.1:d9893d13c628, Apr 6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.True
 
I

Ian Kelly

I much prefer the alternative <> for != but some silly people insisted
that this be removed from Python3.
It's not removed from Python 3, though:

Python 3.3.1 (v3.3.1:d9893d13c628, Apr 6 2013, 20:30:21) [MSC v.1600 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.True

I'd like to see ≠ added as a synonym for !=, even if nobody uses it.
 
S

Steven D'Aprano

So which special methods should the <> operator call? By rights it
ought to call both __gt__ and __lt__ and return True if either of them
is True.

The <> operator comes from Pascal, where it was used as "not equal" since
ASCII doesn't include the ≠ operator. Algol 60, by contrast, used ≠ since
it was invented before ASCII.

The use of ! as "not" is a C-ism and isn't universal.

Given the data types Pascal had as standard back when it was invented, I
think it is fair to say that "less than, or greater than" was logically
equivalent to "not equal to". That's no longer the case though.

Interestingly, later versions of Apple's "Standard Apple Numeric
Environment" (SANE) included separate relational operations for "less
than or greater than" and "not equal to". So if x was a NAN, then you
could have pseudo-code like this:

x != y # true

x <> y # false
 
S

Steven D'Aprano

I would then still write it as not (x == y) to make it clear to myself &
avoid any possible confusion although I think that X != Y is much
cleaner.

I think that is sad. If I read "not (x == y)" I would assume that the
person writing the code didn't understand Python syntax or know its
standard operators.

The exception is if x or y was some unusual type where the __ne__ method
does something different to the logical reverse of the __eq__ method. But
if that is the case, I would expect a comment warning about it. If x and
y were standard objects like floats, strings, etc. then writing out
not (x == y) in full is as sensible as writing out these in full:

x + -y # instead of x - y

alist.insert(len(alist), 99) # instead of alist.append(99)

# instead of adict.clear()
for key in list(adict.keys()):
del adict[key]

x+x+x+x+x+x # instead of x*6


I'm sure any experienced Python programmer can come up with a
hypothetical scenario where you would need to write things out "the long
way", but that doesn't mean that we should do so all the time.

2 lines from the zen stand out here:-

Explicit is better than implicit.
in the face of ambiguity refuse the temptation to guess.

!= is explicit.

There is no ambiguity that needs to be guessed.
 
C

Chris Angelico

So which special methods should the <> operator call? By rights it ought to
call both __gt__ and __lt__ and return True if either of them is True.

Why do you think that? After all, the != operator doesn't call
__factorial__ and __assignment__ and return True if either is True,
does it?

ChrisA

PS. :)
 
D

Dennis Lee Bieber

Ah, well apparently BASIC used it earlier, but I don't know whether it
was an influence on Pascal (except as "what not to do").

Algol was the biggest influence on Pascal, to my understanding --
but by the days of Pascal I suspect ASCII was the prime character set --
so no (ASCII art to ensure it gets through) |--- or =/= characters (I
believe ALGOL 60 used =/= [as a single glyph] for "not equal").
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,766
Messages
2,569,569
Members
45,042
Latest member
icassiem

Latest Threads

Top