Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
0 == 0 is 0
#1
Hi,
I don't understand why 0 == 0 is 0 returns True ? What is the order of priority ?
Although (0==0) is 0 returns False and 0 == (0 is 0) returns False too.

Tx
Reply
#2
From the docs

Quote:Comparisons can be chained arbitrarily, e.g., x < y <= z is equivalent to x < y and y <= z, except that y is evaluated only once (but in both cases z is not evaluated at all when x < y is found to be false).

So, what you have is (0 == 0) and (0 is 0) (note, braces are redundant, just for clarity)


Otherwise equality and identity operators have same priority
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#3
When I run 0==0 is 0, my Python complains about using "is" with a literal. It accepts the program, but says "I have a bad feeling about this."

I used the dis.dis() to look at the bytecodes
from dis import dis

def x():
    0 == 0 is 0

def y():
    (0 == 0) is 0

def z():
    0 == (0 is 0)

print(dis(x))
print(dis(y))
print(dis(z))
Output:
4 0 LOAD_CONST 1 (0) 2 LOAD_CONST 1 (0) 4 DUP_TOP 6 ROT_THREE 8 COMPARE_OP 2 (==) 10 JUMP_IF_FALSE_OR_POP 18 12 LOAD_CONST 1 (0) 14 COMPARE_OP 8 (is) 16 JUMP_FORWARD 4 (to 22) >> 18 ROT_TWO 20 POP_TOP >> 22 POP_TOP 24 LOAD_CONST 0 (None) 26 RETURN_VALUE None 7 0 LOAD_CONST 1 (0) 2 LOAD_CONST 1 (0) 4 COMPARE_OP 2 (==) 6 LOAD_CONST 1 (0) 8 COMPARE_OP 8 (is) 10 POP_TOP 12 LOAD_CONST 0 (None) 14 RETURN_VALUE None 10 0 LOAD_CONST 1 (0) 2 LOAD_CONST 1 (0) 4 LOAD_CONST 1 (0) 6 COMPARE_OP 8 (is) 8 COMPARE_OP 2 (==) 10 POP_TOP 12 LOAD_CONST 0 (None) 14 RETURN_VALUE None
I cannot write different Python code that generates the same bytecode, but this turns out to be a closer match:
from dis import dis

def x():
    return (0 == 0 is 0)

def y():
    if 0 == 0:
        return 0 is 0
    return False

print(dis(x))
print(dis(y))
Output:
4 0 LOAD_CONST 1 (0) 2 LOAD_CONST 1 (0) 4 DUP_TOP 6 ROT_THREE 8 COMPARE_OP 2 (==) 10 JUMP_IF_FALSE_OR_POP 18 12 LOAD_CONST 1 (0) 14 COMPARE_OP 8 (is) 16 RETURN_VALUE >> 18 ROT_TWO 20 POP_TOP 22 RETURN_VALUE None 7 0 LOAD_CONST 1 (0) 2 LOAD_CONST 1 (0) 4 COMPARE_OP 2 (==) 6 POP_JUMP_IF_FALSE 16 8 8 LOAD_CONST 1 (0) 10 LOAD_CONST 1 (0) 12 COMPARE_OP 8 (is) 14 RETURN_VALUE 9 >> 16 LOAD_CONST 2 (False) 18 RETURN_VALUE None
Reply
#4
(Sep-25-2022, 04:37 PM)deanhystad Wrote: When I run 0==0 is 0, my Python complains about using "is" with a literal.

Same with both snippets 0 == 0 is 0 and 0 == 0 and 0 is 0

>>> (0 == 0) and (0 is 0)
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
>>> 0 == 0 is 0
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
True
If you can't explain it to a six year old, you don't understand it yourself, Albert Einstein
How to Ask Questions The Smart Way: link and another link
Create MCV example
Debug small programs

Reply
#5
I don't understand why the tortured bytecode for 0==0 is 0, but the reason for warning about 0 is 0 is because of this.

file junk.py
x = 0
file test.py
import junk
x = 0
print(x==junk.x is x)
When I run test.py
Output:
True
But if I change the value from 0 to 257
Output:
False
And if change the value to 256
Output:
True
The reason for this very odd behavior is Python reuses int objects for common int literals (0 to 256). Int literals outside this range are created on a as needed basis. So if x and y are the same int value, x == y is True, but x is y depends on the value of x.

And to make things more confusing, Python reuses literals when loading your module.
x=257
y=257
print(x==y is x)
Output:
True
Even though x and y are outside the "magic" range, Python only created one int object that is assigned to both x and y. Since 257 is an int, and int objects are immutable, there is no reason to create two int objects. When Python is converting the module to bytecodes it sees that 257 is used twice, and decides to save some space and some time and reuse the 257 int object. This optimization is not possible when the same int constant is used in two different modules (thus the reason for junk.py in my example).

So while 0==0 is 0 is an interesting bit of trivia, it really doesn't matter what value it returns. You should never use code that looks like this.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020