DEV Community

loading...

Python 'is' vs '=='

Kinyanjui Wangonya
πŸ‘¨πŸΎβ€πŸ’»
Originally published at wangonya.com on ・2 min read

A lot of times when I'm doing ifs in Python, I find myself wondering whether to use is or == for the check.

# do I do
if a is b:
    ...

# or
if a == b:
    ...
Enter fullscreen mode Exit fullscreen mode

It can be a bit confusing if you're new to Python, and it's easy to assume the two can be used interchangeably. So, what's the difference?

is

The is operator checks if both elements point to the same object. Let's fire up a python console to help illustrate this:

$ python3
Python 3.7.4
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> a = []
>>> b = []
>>> c = a

>>> a
[]
>>> b
[]
>>> c
[]
>>>
Enter fullscreen mode Exit fullscreen mode

So, we've declared three variables and assigned them values. a and b are both empty lists, and c = a. We can see that all three variables contain an empty list. Using is to compare them:

>>> a is b
False
>>> b is c
False
>>> a is c
True
Enter fullscreen mode Exit fullscreen mode

Despite the fact that a and b seem identical (in that they're both empty lists), the variables a and b do not point to the same object, therefore a is b evaluates to False. The same goes for b is c.

Conversely, because we assigned the variable a to c, they both point to the same object, thus a is c is True.

==

== on the other hand checks if both elements contain equal values. Whether or not they point to the same object doesn't matter here.

>>> a == b
True
>>> b == c
True
>>> a == c
True
Enter fullscreen mode Exit fullscreen mode

All checks using == evaluate to True, because the values of a, b and c are all equal. If d = [1, 2, 3] is introduced, a == d, b == d and c == d would all be False, because the values are not equal.

So if you want to check that elements point to the same object, use is. If you're only interested in the equality of the values, use ==.

Discussion (25)

Collapse
codemouse92 profile image
Jason C. McDonald • Edited

Very nice, but a word of warning, identity (what is checks) is generally a language implementation detail, not something that should be relied upon.

Consider:

spam = 42
eggs = spam
print(spam is eggs)  # True
print(spam is 42)  # True

spam = 420
eggs = spam
print(spam is eggs)  # True
print(spam is 420)  # False

That same example might not work precisely that way in another implementation of Python.

Mutable and immutable values behave very differently in terms of assignment and identity.

Except in some extremely rare, hack-y scenarios, you should only see is in the context of is None.

Collapse
wangonya profile image
Kinyanjui Wangonya Author

Interesting. Thanks for the heads up.

Except in some extremely rare, hack-y scenarios, you should only see is in the context of is None.

You know, I wanted to mention something similar to this but didn't because we wouldn't usually do if a is None... a better way would be if not a - so I didn't know exactly how to frame it.

Collapse
codemouse92 profile image
Jason C. McDonald • Edited

Well, no, you wouldn't want to do that. if not a is the accepted shorthand for if a == False, but False and None are distinct values. You should always explicitly test for None, although you can implicitly test for "not None":

if foo:
    # foo has value (not None) OR foo is True

if not foo:
    # foo is False

if foo is None:
    # foo is None
Thread Thread
wangonya profile image
Kinyanjui Wangonya Author

Awesome.

Thread Thread
dbanty profile image
Dylan Anthony

There's actually a bit more to it than that. if not checks "truthyness", not just equality to False. So not foo will evaluate to True if foo is any of these and more:

  1. False
  2. None
  3. 0
  4. []
  5. {}
  6. ""

The same thing applies in the other direction, if [1] will succeed because the list is not empty, empty list are "falsey" whereas lists containing elements are "truthy".

The lesson here is pretty much don't use if without an explicit comparison (== or is) unless you're sure you know how truthy the value will be in all cases.

Collapse
ardraeiss profile image
Mikhail Merzlyutin

There are some corner cases when you would like to use the full comparison form. For example if None is used as an "no argument value was passed" flag:

def foo(a=None):
 if not a:
  print("No value provided")

it will print message for calls foo(), foo(0), foo(""), foo([]).

Thread Thread
codemouse92 profile image
Jason C. McDonald

Yes, it's always best to test for the presence of None explicitly, rather than implicitly.

Collapse
aminmansuri profile image
hidden_dude

wouldn't 'is' be used in s scenario where we're comparing pointers like in a linked list?

while p is not q :
p = p.next

I think that is how 'is' should be used.

Thread Thread
wangonya profile image
Kinyanjui Wangonya Author • Edited

I've not used linked lists much so I wouldn't know but yeah, I guess that would work.

Thread Thread
codemouse92 profile image
Jason C. McDonald

Well, Python doesn't have pointers, per se, nor would there ordinarily be a cause to implement your own linked list. It's virtually always best to use Python's own data structures, or at least build upon them.

Thread Thread
aminmansuri profile image
hidden_dude

yes.. but if you needed something fancy like a left leaning red black tree or a concurrent skip list you'd need 'is' to work for you for completeness.

(ps. I know they don't really have "pointers" but in these scenarios you use it like a pointer)

Collapse
derrickwango profile image
DerrickWango

I'm so happy to see a fellow Kenyan here.Thank you.

Collapse
zenulabidin profile image
Ali Sherief

If you try to compare a variable with a literal using is or is not you will get a syntax warning like this:

>>> x=1
>>> x is 0
<stdin>:1: SyntaxWarning: "is" with a literal. Did you mean "=="?
False
>>> x is not 0
<stdin>:1: SyntaxWarning: "is not" with a literal. Did you mean "!="?
True
Collapse
hanpari profile image
Pavel Morava

The most basic explanation would be that is presents syntax sugar for

id(x) = id(y)

In terms of CPython this would represent if pointer leading to x equals to the pointer leading to y.

Don't forget that CPython stores all its objects on the heap.

Collapse
jannikwempe profile image
Jannik Wempe

Isn't a is b essentially the same as id(a) == id(b)?

Collapse
wangonya profile image
Kinyanjui Wangonya Author

Haven't tried it out on a console, but it makes sense. I think it's the same.

Collapse
skyandsand profile image
Chris C

So basically

is

checks to see if the variable is the same space in memory, while

==

checks to see if the value is identical?

Collapse
wangonya profile image
Kinyanjui Wangonya Author

That's how I understand it, yes.

Collapse
jodyshop profile image
Waleed Barakat

Nice explanation, I used to compare if s in PHP , but this is interesting

Collapse
vikctar profile image
vikctar

Nice. I always enjoy reading your posts.

Collapse
wangonya profile image
Kinyanjui Wangonya Author

Thanks!

Collapse
davidmm1707 profile image
David MM🐍

Nice and concise. Thanks.

Collapse
tesfaozem profile image
Tesfa

Almost made a very very costly mistake with this.Thank you for the article.

Collapse
mikefromru profile image
Mike Ru

Thank you so much.

Collapse
wangonya profile image
Kinyanjui Wangonya Author

You're welcome! πŸ™‚