Categories
equality python reference semantics

Is there a difference between “==” and “is”?

629

My Google-fu has failed me.

In Python, are the following two tests for equality equivalent?

n = 5
# Test one.
if n == 5:
    print 'Yay!'

# Test two.
if n is 5:
    print 'Yay!'

Does this hold true for objects where you would be comparing instances (a list say)?

Okay, so this kind of answers my question:

L = []
L.append(1)
if L == [1]:
    print 'Yay!'
# Holds true, but...

if L is [1]:
    print 'Yay!'
# Doesn't.

So == tests value where is tests to see if they are the same object?

0

    1091

    is will return True if two variables point to the same object (in memory), == if the objects referred to by the variables are equal.

    >>> a = [1, 2, 3]
    >>> b = a
    >>> b is a 
    True
    >>> b == a
    True
    
    # Make a new copy of list `a` via the slice operator, 
    # and assign it to variable `b`
    >>> b = a[:] 
    >>> b is a
    False
    >>> b == a
    True
    

    In your case, the second test only works because Python caches small integer objects, which is an implementation detail. For larger integers, this does not work:

    >>> 1000 is 10**3
    False
    >>> 1000 == 10**3
    True
    

    The same holds true for string literals:

    >>> "a" is "a"
    True
    >>> "aa" is "a" * 2
    True
    >>> x = "a"
    >>> "aa" is x * 2
    False
    >>> "aa" is intern(x*2)
    True
    

    Please see this question as well.

    6

    • 2

      I found that: echo 'import sys;tt=sys.argv[1];print(tt is "foo", tt == "foo", id(tt)==id("foo"))'| python3 - foo output: False True False.

      – ahuigo

      Jul 23, 2018 at 12:38

    • You lost me with the b = a[:] slice operator list copy part, so I’ve edited your answer to have a comment there. Looks like I just reached the threshold to not have to have my edits reviewed before they apply, so hopefully that’s cool with you. Regardless, here’s a useful reference for how to copy lists that I came across and had to reference to figure out what you were doing: stackoverflow.com/a/2612815/4561887

      Jan 22, 2019 at 21:14


    • 9

      1000 is 10**3 evaluates to True in Python 3.7 since 10**3 is type int. But 1000 is 1e3 evaluates to False since 1e3 is type float.

      Sep 8, 2019 at 1:13


    • 2

      @AhmedFasih Whether or not 1000 is 10**3 is true is implementation dependent, and depends on the compiler pre-evaluating the expression 10**3. x=10; 1000 is x**3 evaluates to False.

      – chepner

      May 27, 2020 at 12:41

    • 1

      Just a side note. Python 3.8 and onwards return a SyntaxWarning when comparing literal like 1000 is 10**3: SyntaxWarning: "is" with a literal. Did you mean "=="?

      Jan 11 at 9:52


    373

    There is a simple rule of thumb to tell you when to use == or is.

    • == is for value equality. Use it when you would like to know if two objects have the same value.
    • is is for reference equality. Use it when you would like to know if two references refer to the same object.

    In general, when you are comparing something to a simple type, you are usually checking for value equality, so you should use ==. For example, the intention of your example is probably to check whether x has a value equal to 2 (==), not whether x is literally referring to the same object as 2.


    Something else to note: because of the way the CPython reference implementation works, you’ll get unexpected and inconsistent results if you mistakenly use is to compare for reference equality on integers:

    >>> a = 500
    >>> b = 500
    >>> a == b
    True
    >>> a is b
    False
    

    That’s pretty much what we expected: a and b have the same value, but are distinct entities. But what about this?

    >>> c = 200
    >>> d = 200
    >>> c == d
    True
    >>> c is d
    True
    

    This is inconsistent with the earlier result. What’s going on here? It turns out the reference implementation of Python caches integer objects in the range -5..256 as singleton instances for performance reasons. Here’s an example demonstrating this:

    >>> for i in range(250, 260): a = i; print "%i: %s" % (i, a is int(str(i)));
    ... 
    250: True
    251: True
    252: True
    253: True
    254: True
    255: True
    256: True
    257: False
    258: False
    259: False
    

    This is another obvious reason not to use is: the behavior is left up to implementations when you’re erroneously using it for value equality.

    3

    • 1

      With regards to the first example of a=500 and b=500, just wanted to point out that if you set a and b to an interger between [-5, 256], a is b actually returns True. More information here: stackoverflow.com/q/306313/7571052

      Jan 30, 2019 at 18:01

    • 1

      @AsheKetchum, yes, note that I wrote “It turns out the reference implementation of Python caches integer objects in the range -5..256 as singleton instances for performance reasons.”

      Jan 31, 2019 at 21:38

    • Just like to add my two bits here. Use is if you want to check if its the same object (say you have a list of city and route objects each; you could compare the locations, or merely check if its the same city or not – so is is the stronger comparison here). Else if you’re only concerned about primitives, usually == will suffice. This is more of a thumb rule that will get violated when the going gets tough

      – user11991978

      Oct 30, 2020 at 9:59

    56

    Is there a difference between == and is in Python?

    Yes, they have a very important difference.

    ==: check for equality – the semantics are that equivalent objects (that aren’t necessarily the same object) will test as equal. As the documentation says:

    The operators <, >, ==, >=, <=, and != compare the values of two objects.

    is: check for identity – the semantics are that the object (as held in memory) is the object. Again, the documentation says:

    The operators is and is not test for object identity: x is y is true
    if and only if x and y are the same object. Object identity is
    determined using the id() function. x is not y yields the inverse
    truth value.

    Thus, the check for identity is the same as checking for the equality of the IDs of the objects. That is,

    a is b
    

    is the same as:

    id(a) == id(b)
    

    where id is the builtin function that returns an integer that “is guaranteed to be unique among simultaneously existing objects” (see help(id)) and where a and b are any arbitrary objects.

    Other Usage Directions

    You should use these comparisons for their semantics. Use is to check identity and == to check equality.

    So in general, we use is to check for identity. This is usually useful when we are checking for an object that should only exist once in memory, referred to as a “singleton” in the documentation.

    Use cases for is include:

    • None
    • enum values (when using Enums from the enum module)
    • usually modules
    • usually class objects resulting from class definitions
    • usually function objects resulting from function definitions
    • anything else that should only exist once in memory (all singletons, generally)
    • a specific object that you want by identity

    Usual use cases for == include:

    • numbers, including integers
    • strings
    • lists
    • sets
    • dictionaries
    • custom mutable objects
    • other builtin immutable objects, in most cases

    The general use case, again, for ==, is the object you want may not be the same object, instead it may be an equivalent one

    PEP 8 directions

    PEP 8, the official Python style guide for the standard library also mentions two use-cases for is:

    Comparisons to singletons like None should always be done with is or
    is not, never the equality operators.

    Also, beware of writing if x when you really mean if x is not None
    e.g. when testing whether a variable or argument that defaults to None
    was set to some other value. The other value might have a type (such
    as a container) that could be false in a boolean context!

    Inferring equality from identity

    If is is true, equality can usually be inferred – logically, if an object is itself, then it should test as equivalent to itself.

    In most cases this logic is true, but it relies on the implementation of the __eq__ special method. As the docs say,

    The default behavior for equality comparison (== and !=) is based on
    the identity of the objects. Hence, equality comparison of instances
    with the same identity results in equality, and equality comparison of
    instances with different identities results in inequality. A
    motivation for this default behavior is the desire that all objects
    should be reflexive (i.e. x is y implies x == y).

    and in the interests of consistency, recommends:

    Equality comparison should be reflexive. In other words, identical
    objects should compare equal:

    x is y implies x == y

    We can see that this is the default behavior for custom objects:

    >>> class Object(object): pass
    >>> obj = Object()
    >>> obj2 = Object()
    >>> obj == obj, obj is obj
    (True, True)
    >>> obj == obj2, obj is obj2
    (False, False)
    

    The contrapositive is also usually true – if somethings test as not equal, you can usually infer that they are not the same object.

    Since tests for equality can be customized, this inference does not always hold true for all types.

    An exception

    A notable exception is nan – it always tests as not equal to itself:

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

    Checking for identity can be much a much quicker check than checking for equality (which might require recursively checking members).

    But it cannot be substituted for equality where you may find more than one object as equivalent.

    Note that comparing equality of lists and tuples will assume that identity of objects are equal (because this is a fast check). This can create contradictions if the logic is inconsistent – as it is for nan:

    >>> [nan] == [nan]
    True
    >>> (nan,) == (nan,)
    True
    

    A Cautionary Tale:

    The question is attempting to use is to compare integers. You shouldn’t assume that an instance of an integer is the same instance as one obtained by another reference. This story explains why.

    A commenter had code that relied on the fact that small integers (-5 to 256 inclusive) are singletons in Python, instead of checking for equality.

    Wow, this can lead to some insidious bugs. I had some code that checked if a is b, which worked as I wanted because a and b are typically small numbers. The bug only happened today, after six months in production, because a and b were finally large enough to not be cached. – gwg

    It worked in development. It may have passed some unittests.

    And it worked in production – until the code checked for an integer larger than 256, at which point it failed in production.

    This is a production failure that could have been caught in code review or possibly with a style-checker.

    Let me emphasize: do not use is to compare integers.

    9

    • “do not use is at all” would be a good rule too. The idiomatic is None being an exception, but that said == None works too…

      Jul 24, 2019 at 6:20

    • @Jean-FrançoisFabre Another exception: The official documentation seems to recommend using is for comparing Enums.

      – Arthur

      Feb 10, 2020 at 17:30


    • is that mean two custom classes compare, like a = Car(“new”), B=Car(“new”), if we use a==b, this is equal to a is b, am i right?

      – Haskell

      Aug 6, 2020 at 6:23

    • @UniSize I don’t think you are right. Problems: 1. you say a, and B, but then you say a==b (lowercase) and Python is case-sensitive. 2. you don’t say whether a and b are supposed to be equivalent, but two instantiations with the same arguments imply that they are equivalent, but not the same objects, thus you would be wrong in your interpretation. Please reread my answer here and let me know what’s missing, and be careful and explicit in your response.

      Aug 6, 2020 at 14:29

    • @AaronHall My appology, first of all, it’s a typo. I revised it, a = Car(“new”), b=Car(“new”), if we use a==b, is this equal to a is b? I understand that “is” is checking whether two objects are in the same memory location, and a==b is the comparison between two objects. Based on the testing, a==b return false, and a is b return false as well. With the same initialization, why will a==b return false?

      – Haskell

      Aug 7, 2020 at 4:38