1220

I've got a Python program where two variables are set to the value 'public'. In a conditional expression I have the comparison var1 is var2 which fails, but if I change it to var1 == var2 it returns True.

Now if I open my Python interpreter and do the same "is" comparison, it succeeds.

>>> s1 = 'public'
>>> s2 = 'public'
>>> s2 is s1
True

What am I missing here?

martineau
  • 99,260
  • 22
  • 139
  • 249
jottos
  • 19,028
  • 9
  • 28
  • 26
  • 9
    see: http://stackoverflow.com/questions/1392433/python-why-is-hello-is-hello – Nick Dandoulakis Oct 01 '09 at 15:50
  • 3
    This problem also occurs when you read a console input via e.g.: `input = raw_input("Decide (y/n): ")`. In this case an input of "y" and `if input == 'y':`will return "True" while `if input is 'y':` will return False. – Semjon Mössinger Aug 21 '16 at 11:09
  • 4
    This blog provides a far more complete explanation than any answer http://guilload.com/python-string-interning/ – Chris_Rands Oct 05 '16 at 08:04
  • 1
    As @chris-rico mentions, I great explanation here http://stackoverflow.com/q/15541404/1695680 – ThorSummoner Oct 06 '16 at 15:43
  • can you explain specifically why in the original poster example the "is" operator fail on the script but the same operator on the same strings return "true" on the interactive mode? It's the same interpreter, so we should expect the same behaviour about interning whatever you have it run a script or run in interactive mode, right? – robertspierre Jun 13 '17 at 18:04
  • 4
    Possible duplicate of [Is there a difference between \`==\` and \`is\` in Python?](https://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is-in-python) – Taknok Aug 14 '17 at 19:24
  • Unless you're checking that something `is None` or `is not None`, you should basically never use `is`. – Boris Nov 11 '19 at 05:59

15 Answers15

1599

is is identity testing, == is equality testing. what happens in your code would be emulated in the interpreter like this:

>>> a = 'pub'
>>> b = ''.join(['p', 'u', 'b'])
>>> a == b
True
>>> a is b
False

so, no wonder they're not the same, right?

In other words: a is b is the equivalent of id(a) == id(b)

Hari
  • 927
  • 2
  • 13
  • 21
SilentGhost
  • 264,945
  • 58
  • 291
  • 279
  • 18
    ahh same as eq? vs equal? in scheme, got it. – jottos Oct 01 '09 at 17:00
  • 4
    There's a lot of equality predicates in Common Lisp, besides the basic hierarchy of eq, eql, equal, and equalp (the longer the name there, the more things will be found equal). – David Thornley Oct 01 '09 at 19:43
  • 51
    Or `==` vs `.equals()` in Java. The best part is that the Python `==` is not analogous to the Java `==`. – MatrixFrog Feb 04 '12 at 02:48
  • 1
    And what with the `None` value? – Крайст Oct 27 '12 at 19:47
  • 12
    @Крайст: there is only a single `None` value. So it always has the same id. – SilentGhost Oct 29 '12 at 09:57
  • @SilentGhost: GvR in PEP8 says that we must never check equality and use only `is None` expression. Read about it yesterday after commented that above. – Крайст Oct 29 '12 at 20:05
  • 1
    Simple, one-line test: `a = 'pub'; b = ''.join(a); a == b, a is b` – Noctis Skytower Apr 11 '13 at 14:11
  • 22
    This doesn't address the OP's "is -> True" example. – user2864740 Sep 10 '14 at 04:53
  • 4
    why do "s2 is s1" is True in the question then? – アレックス Oct 10 '14 at 09:44
  • 7
    @AlexanderSupertramp, because of [string interning](http://stackoverflow.com/questions/15541404/python-string-interning). – Chris Rico Feb 01 '15 at 09:34
  • Here's an excellent [article on StackAbuse](https://stackabuse.com/comparing-strings-using-python/) explaining this and a few related matters – pfabri Mar 13 '19 at 13:40
  • 3
    @pfabri: That's a *terrible* article. It includes the atrocious recommendation "A rule of thumb to follow is to use `==` when comparing immutable types (like ints) and `is` when comparing objects." You almost *never* want `is` for comparing user-defined objects. The correct rule of thumb is "Use `==` for *everything* but `None` and `NotImplemented` comparisons until you understand what you're doing." The article also fails to convey that the identity semantics of `int`s are a CPython implementation detail that only applies to small of `int`s, not some caching mechanism common to all `int`s. – ShadowRanger Jul 11 '19 at 16:31
613

Other answers here are correct: is is used for identity comparison, while == is used for equality comparison. Since what you care about is equality (the two strings should contain the same characters), in this case the is operator is simply wrong and you should be using == instead.

The reason is works interactively is that (most) string literals are interned by default. From Wikipedia:

Interned strings speed up string comparisons, which are sometimes a performance bottleneck in applications (such as compilers and dynamic programming language runtimes) that rely heavily on hash tables with string keys. Without interning, checking that two different strings are equal involves examining every character of both strings. This is slow for several reasons: it is inherently O(n) in the length of the strings; it typically requires reads from several regions of memory, which take time; and the reads fills up the processor cache, meaning there is less cache available for other needs. With interned strings, a simple object identity test suffices after the original intern operation; this is typically implemented as a pointer equality test, normally just a single machine instruction with no memory reference at all.

So, when you have two string literals (words that are literally typed into your program source code, surrounded by quotation marks) in your program that have the same value, the Python compiler will automatically intern the strings, making them both stored at the same memory location. (Note that this doesn't always happen, and the rules for when this happens are quite convoluted, so please don't rely on this behavior in production code!)

Since in your interactive session both strings are actually stored in the same memory location, they have the same identity, so the is operator works as expected. But if you construct a string by some other method (even if that string contains exactly the same characters), then the string may be equal, but it is not the same string -- that is, it has a different identity, because it is stored in a different place in memory.

Daniel Pryden
  • 54,536
  • 12
  • 88
  • 131
  • 6
    Where can someone read more on the convoluted rules for when strings are interned? – Noctis Skytower Apr 11 '13 at 14:14
  • 96
    +1 for a thorough explanation. Not sure how the other answer received so many upvotes without explaining what ACTUALLY happened. – That1Guy Apr 29 '13 at 02:07
  • 4
    this is exactly what I thought of when I read the question. The accepted answer is short yet contains the fact, but this answer *explains* things far better. Nice! – Sнаđошƒаӽ Jul 19 '15 at 05:46
  • 3
    @NoctisSkytower Googled the same and found this http://guilload.com/python-string-interning/ – xtreak Mar 10 '16 at 14:41
  • So the general rule of thumb is to always use `==`/`!=` when the strings are created via different methods? – naught101 Oct 18 '16 at 00:42
  • 5
    @naught101: No, the rule is to choose between `==` and `is` based on what kind of check you want. If you care about the strings being *equal* (that is, having the same contents) then you should always use `==`. If you care about whether any two Python names refer to the same object instance, you should use `is`. You might need `is` if you're writing code that handles lots of different values without caring about their contents, or else if you know there is only one of something and you want to ignore other objects pretending to be that thing. If you're not sure, always chose `==`. – Daniel Pryden Oct 18 '16 at 19:30
  • Does this imply that python string comparison via `==` first checks for object identity and then, failing that, for string equality? – Him Aug 27 '18 at 18:32
  • 1
    @Scott: Yes, as a performance optimization, the CPython implementation does do an identity check first. I don't think it's guaranteed by the language spec though. – Daniel Pryden Aug 27 '18 at 19:27
  • this is the bit the first answer missed, the string public was interned as an object and the two variables pointed to the same object so id(s1) is id(s2) – jottos Dec 29 '19 at 20:02
111

The is keyword is a test for object identity while == is a value comparison.

If you use is, the result will be true if and only if the object is the same object. However, == will be true any time the values of the object are the same.

Thomas Owens
  • 107,741
  • 94
  • 299
  • 427
60

One last thing to note, you may use the sys.intern function to ensure that you're getting a reference to the same string:

>>> from sys import intern
>>> a = intern('a')
>>> a2 = intern('a')
>>> a is a2
True

As pointed out above, you should not be using is to determine equality of strings. But this may be helpful to know if you have some kind of weird requirement to use is.

Note that the intern function used to be a builtin on Python 2 but was moved to the sys module in Python 3.

Boris
  • 7,044
  • 6
  • 62
  • 63
Jason Baker
  • 171,942
  • 122
  • 354
  • 501
47

is is identity testing and == is equality testing. This means is is a way to check whether two things are the same things, or just equivalent.

Say you've got a simple person object. If it is named 'Jack' and is '23' years old, it's equivalent to another 23-year-old Jack, but it's not the same person.

class Person(object):
   def __init__(self, name, age):
       self.name = name
       self.age = age

   def __eq__(self, other):
       return self.name == other.name and self.age == other.age

jack1 = Person('Jack', 23)
jack2 = Person('Jack', 23)

jack1 == jack2 # True
jack1 is jack2 # False

They're the same age, but they're not the same instance of person. A string might be equivalent to another, but it's not the same object.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
TankorSmash
  • 11,146
  • 5
  • 55
  • 96
  • 1
    If you change set `jack1.age = 99`, that won't change `jack2.age`. That's because they are two different instances, so `jack1 is not jack2`. However, they can equal each other `jack1 == jack2` if their name and their age are the same. It gets more complicated for strings, because strings are immutable in Python, and Python often reuses the same instance. I like this explanation because it uses the simple cases (a normal object) rather then the special cases (strings). – Flimm Feb 10 '20 at 07:57
39

This is a side note, but in idiomatic Python, you will often see things like:

if x is None:
    # Some clauses

This is safe, because there is guaranteed to be one instance of the Null Object (i.e., None).

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Gregg Lind
  • 18,936
  • 15
  • 63
  • 80
30

If you're not sure what you're doing, use the '=='. If you have a little more knowledge about it you can use 'is' for known objects like 'None'.

Otherwise you'll end up wondering why things doesn't work and why this happens:

>>> a = 1
>>> b = 1
>>> b is a
True
>>> a = 6000
>>> b = 6000
>>> b is a
False

I'm not even sure if some things are guaranteed to stay the same between different python versions/implementations.

Mattias Nilsson
  • 3,426
  • 1
  • 20
  • 27
  • 1
    Interesting example showing how reassigning ints makes triggers this condition. Why did this fail? Is it due to intern-ing or something else? – Paul Dec 22 '14 at 16:49
  • It looks like the reason the is returns false may due to the interpreter implementation: http://stackoverflow.com/questions/132988/is-there-a-difference-between-and-is-in-python – Paul Dec 22 '14 at 16:55
  • 1
    Read : http://stackoverflow.com/questions/306313/pythons-is-operator-behaves-unexpectedly-with-integers and http://stackoverflow.com/questions/11476190/why-0-6-is-6-false – Archit Jain Dec 26 '15 at 13:04
  • @ArchitJain Yes, those links explain it pretty well. When you read them, you'll know what numbers you can use 'is' on. I just wish they would explain why it is still not a good idea to do that :) You knowing this does not make it a good idea to assume everyone else does as well (or that the internalized number range will never change) – Mattias Nilsson Dec 29 '15 at 13:32
23

From my limited experience with python, is is used to compare two objects to see if they are the same object as opposed to two different objects with the same value. == is used to determine if the values are identical.

Here is a good example:

>>> s1 = u'public'
>>> s2 = 'public'
>>> s1 is s2
False
>>> s1 == s2
True

s1 is a unicode string, and s2 is a normal string. They are not the same type, but are the same value.

Jack M.
  • 24,959
  • 6
  • 50
  • 65
  • 1
    This result is due to a different reason: comparing a unicode string (``) to a non-unicode string (``). It is behavior specific to Python 2. In Python 3, both of `s1` and are of type `str`, and both `is` and `==` return `True`. – Ioannis Filippidis Apr 17 '21 at 11:38
20

I think it has to do with the fact that, when the 'is' comparison evaluates to false, two distinct objects are used. If it evaluates to true, that means internally it's using the same exact object and not creating a new one, possibly because you created them within a fraction of 2 or so seconds and because there isn't a large time gap in between it's optimized and uses the same object.

This is why you should be using the equality operator ==, not is, to compare the value of a string object.

>>> s = 'one'
>>> s2 = 'two'
>>> s is s2
False
>>> s2 = s2.replace('two', 'one')
>>> s2
'one'
>>> s2 is s
False
>>> 

In this example, I made s2, which was a different string object previously equal to 'one' but it is not the same object as s, because the interpreter did not use the same object as I did not initially assign it to 'one', if I had it would have made them the same object.

meder omuraliev
  • 171,706
  • 64
  • 370
  • 423
  • 5
    Using `.replace()` as an example in this context is probably not the best, though, because its semantics can be confusing. `s2 = s2.replace()` will *always* create a *new* string object, assign the new string object to `s2`, and then dispose of the string object that `s2` used to point to. So even if you did `s = s.replace('one', 'one')` you would still get a new string object. – Daniel Pryden Oct 01 '09 at 16:20
15

I believe that this is known as "interned" strings. Python does this, so does Java, and so do C and C++ when compiling in optimized modes.

If you use two identical strings, instead of wasting memory by creating two string objects, all interned strings with the same contents point to the same memory.

This results in the Python "is" operator returning True because two strings with the same contents are pointing at the same string object. This will also happen in Java and in C.

This is only useful for memory savings though. You cannot rely on it to test for string equality, because the various interpreters and compilers and JIT engines cannot always do it.

Zan Lynx
  • 49,393
  • 7
  • 74
  • 125
14

Actually, the is operator checks for identity and == operator checks for equality.

From the language reference:

Types affect almost all aspects of object behavior. Even the importance of object identity is affected in some sense: for immutable types, operations that compute new values may actually return a reference to any existing object with the same type and value, while for mutable objects this is not allowed. E.g., after a = 1; b = 1, a and b may or may not refer to the same object with the value one, depending on the implementation, but after c = []; d = [], c and d are guaranteed to refer to two different, unique, newly created empty lists. (Note that c = d = [] assigns the same object to both c and d.)

So from the above statement we can infer that the strings, which are immutable types, may fail when checked with "is" and may succeed when checked with "is".

The same applies for int and tuple which are also immutable types.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Ram
  • 1,075
  • 8
  • 20
12

The == operator tests value equivalence. The is operator tests object identity, and Python tests whether the two are really the same object (i.e., live at the same address in memory).

>>> a = 'banana'
>>> b = 'banana'
>>> a is b
True

In this example, Python only created one string object, and both a and b refers to it. The reason is that Python internally caches and reuses some strings as an optimization. There really is just a string 'banana' in memory, shared by a and b. To trigger the normal behavior, you need to use longer strings:

>>> a = 'a longer banana'
>>> b = 'a longer banana'
>>> a == b, a is b
(True, False)

When you create two lists, you get two objects:

>>> a = [1, 2, 3]
>>> b = [1, 2, 3]
>>> a is b
False

In this case we would say that the two lists are equivalent, because they have the same elements, but not identical, because they are not the same object. If two objects are identical, they are also equivalent, but if they are equivalent, they are not necessarily identical.

If a refers to an object and you assign b = a, then both variables refer to the same object:

>>> a = [1, 2, 3]
>>> b = a
>>> b is a
True
Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
X. Wang
  • 733
  • 8
  • 16
7

is will compare the memory location. It is used for object-level comparison.

== will compare the variables in the program. It is used for checking at a value level.

is checks for address level equivalence

== checks for value level equivalence

johnashu
  • 2,101
  • 2
  • 14
  • 34
2

is is identity testing and == is equality testing (see the Python documentation).

In most cases, if a is b, then a == b. But there are exceptions, for example:

>>> nan = float('nan')
>>> nan is nan
True
>>> nan == nan
False

So, you can only use is for identity tests, never equality tests.

Peter Mortensen
  • 28,342
  • 21
  • 95
  • 123
Ryan
  • 177
  • 2
  • 5
-1

The basic concept we have to be clear while approaching this question is to understand the difference between is and ==.

"is" is will compare the memory location. if id(a)==id(b), then a is b returns true else it returns false.

so, we can say that is is used for comparing memory locations. Whereas,

== is used for equality testing which means that it just compares only the resultant values. The below shown code may acts as an example to the above given theory.

code

Click here for the code

In the case of string literals(strings without getting assigned to variables), the memory address will be same as shown in the picture. so, id(a)==id(b). remaining this is self-explanatory.

flaxel
  • 2,706
  • 4
  • 9
  • 22