9

When in a Python interactive session:

In [1]: a = "my string"

In [2]: b = "my string"

In [3]: a == b
Out[3]: True

In [4]: a is b
Out[4]: False

In [5]: import sys

In [6]: print(sys.version)
3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]

On the other hand, when running the following program:

#!/usr/bin/env python

import sys


def test():
    a = "my string"
    b = "my string"
    print(a == b)
    print(a is b)


if __name__ == "__main__":
    test()
    print(sys.version)

The output is:

True
True
3.5.2 (default, Nov 17 2016, 17:05:23) 
[GCC 5.4.0 20160609]

Why a is b has different outcome in the above two cases?

I am aware of this answer (and of course the difference between the == and is operators! that is the point of the question!) but aren't a and b the same object also in the first case? (interpeter?) since they point to the same (immutable) string?

Community
  • 1
  • 1
pkaramol
  • 16,451
  • 43
  • 149
  • 324
  • 1
    Possible duplicate of [Is there a difference between \`==\` and \`is\` in Python?](http://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is-in-python) – Amin Etesamian Jan 24 '17 at 22:17
  • 1
    You'd have to check the cpython source code, but I'd imagine that the python interpreter is smart enough to realise that both those strings are the same and since strings are immutable its safe to point both variables to the same instance. Therefore an `is` check returns true. For the REPL as the strings are input incrementally there is no such optimization opportunity and both variables refer to different objects. – Paul Rooney Jan 24 '17 at 22:19
  • 4
    @AminEtesamian From what I understand, the question is rather on why the ids differs when using interpreter but are the same when running a .py file. I think pkaramol understands the difference between is and ==. – HolyDanna Jan 24 '17 at 22:20
  • I believe Paul is correct, when interpreting there is an opportunity for introspection and reuse, in the interpreter it just makes a new object instead. – GRAYgoose124 Jan 24 '17 at 22:21

2 Answers2

7

This is caused by string interning. See this question for another example.

In your example, CPython interns the string constants in the module but doesn't in the REPL.

Community
  • 1
  • 1
emulbreh
  • 3,421
  • 23
  • 27
  • 2
    See [this](http://stackoverflow.com/a/25267946/2076832) answer for more information. – GRAYgoose124 Jan 24 '17 at 22:30
  • 2
    Correction. This is not string interning at fault. This has to do with constant folding. See [here](https://paste.pound-python.org/show/1lMKJxdj7mgR3doK98XS/) – GRAYgoose124 Jan 24 '17 at 22:49
  • @GRAYgoose124 is right, code objects deduplicate their constants. Also, the example string contains a space and is not interned by default. Please write an answer, I'll delete mine. – emulbreh Jan 25 '17 at 22:23
1

So the console creates two different objects when creating two strings, but the interpreter, when running code in a single function will reuse the memory location of identical strings. Here is how to check if this is happening to you:

a = "my string"
b = "my string"

print id(a)
print id(b)

If these two ids are the same, then a is b will return True, if not then it will return False

Looks like you are using anaconda, so I checked this in the console and found different ids and then wrote a function in the editor and executed it and got the same ids.

Note: Now that we know that is determines if two variable labels point to the same object in memory, I should say that is should be used sparingly. It is usually used to compare singletons like None a is None, for example. So don't use it to compare objects, use ==, and when creating classes implement the __eq__ method so you can use the == operator.