-2

There is this post on Instagram where the author says if num3 and num4 are set to 257 and num3 is num4 is evaluated you should get False.

I have revised the code adding some conditions but I am getting True. I saw that integers until 256 are assigned the same memory bucket for the same value but not for 257 onward. So what is happening?

num1 = 256
num2 = 256

if num1 == num2:
    print(True)

num3 = 257
num4 = 257

if num3 == num4:
    print(True)
    if num3 is num4:
        print(True)
    else:
        print(False)
mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Milad
  • 29
  • 5
  • `257` is exactly equal to `257`. Not quite sure why people would think otherwise. – Obsidian Age Jan 21 '20 at 02:12
  • Try python3 REPL. Type in num3=257 and then num4=257. Then type num3 is num4 to see that the result is False. Now, run the OPs program and notice that `if num3 is num4` returns `True`. An answer explaining that will help OP. – zedfoxus Jan 21 '20 at 02:25
  • Yeah, that's a good point @mkrieger1. It seems from the description that the OP wants to understand `==` and `is` comparison for 256 and 257. I find it interesting that REPL gives different results from the OPs program. – zedfoxus Jan 21 '20 at 02:28

2 Answers2

4

is will return True if two variables point to the same object

== if the objects referred to by the variables are equal.

Run in script:

is returns True

Because both num3 and num4 point to the same object:

# id() to get the unique identifier of an object    
print(id(num3) , id(num4)) 

55080624 55080624

== also returns True

num3 = 257
num4 = 257

as both refer to <class 'int'> 257

Run in REPL :

is returns False

Because both num3 and num4 point to the different objects:

# id() to get the unique identifier of an object    
print(id(num3) , id(num4)) 

34836272 39621264

== returns True

num3 = 257
num4 = 257

as both refer to <class 'int'> 257

The reason you have different result is from Why does the `is` operator behave differently in a script vs the REPL?

When you run code in a .py script, the entire file is compiled into a code object before executing it. In this case, CPython is able to make certain optimizations - like reusing the same instance for the integer 300.

So in your case, both num3 and num4 refer to <class 'int'> 257. in REPL you have different object ids, however after the file is compiled and optimized to same object id if you run them in script.

Regards to the different behaviors of 256 and 257 :

"is" operator behaves unexpectedly with integers

What's with the integer cache maintained by the interpreter?

in short, objects representing values from -5 to +256 are created at startup time, so if you have number range -5 to 256 you get the same object id in REPL, for any int <-5 and > 256,they will be assigned to a new object id.

for example :

num5 = -6
num6 = -6 

print(id(num5),id(num6))

39621232 39621136

num7 = 258
num8 = 258

print(id(num7),id(num8))

39621296 39621328
Ray
  • 1,539
  • 1
  • 14
  • 27
2

If you look at the post again, you can see that num3 == num4 is True, but num3 is num4 is False. This has to do with item ids. == compares the values of the variables, while is compares their ids. You can see each of their ids using id(num3) and id(num4). They should be different when values are higher than 256. Reason for this is that Python stores low number values automatically, and variables assigned to these low numbers will point to the same id. Python does this because they are so commonly used. But larger numbers aren't created until Python needs them. So variables are given their own ids.

Edit:

There seems to be different behavior when running a script vs. REPL. The original Instagram post was using REPL, and I replicated the False comparison using REPL. Running a script evaluated True for me though.

schwartz721
  • 767
  • 7
  • 19
  • 1
    Run the program OP has and notice that `if num3 is num4` results in `True` instead of `False`. – zedfoxus Jan 21 '20 at 02:22
  • @zedfoxus I ran it in Python 3.5.2 and Python 3.8.1, and the last thing printed (i.e. for `num3 is num4`) is `False` in both versions. Which version are you getting `True` in? – kaya3 Jan 21 '20 at 02:29
  • I just ran this in 3.8.1 in REPL and got False, but when run as a script got True. The Instagram post referenced in the question is REPL – schwartz721 Jan 21 '20 at 02:31
  • 2
    I am using `Python 3.7.4 (default, Sep 7 2019, 18:27:02) ` on OSX. In REPL I get False. When running program with `python3 file.py` I get True. – zedfoxus Jan 21 '20 at 02:33
  • 2
    I see. My suspicion is that equal constants are being de-duplicated when referenced from the same code object, but not being de-duplicated when referenced from different code objects. The script is compiled to one code object, and each line in the REPL is compiled to its own code object. – kaya3 Jan 21 '20 at 02:34
  • 1
    Yeah, Raymond shared a link as a comment to his answer and that helped me realize how CPython may be referencing, @kaya3. That's so interesting. – zedfoxus Jan 21 '20 at 02:41