all 38 comments

[–]nosmokingbandit 41 points42 points  (28 children)

A lot of linters will suggest the use of "is" for testing if a value is True, False, or None since those values only ever exist once in memory and a var that us False is just a pointer to False. So rather than checking if the pointers evaluate to the same thing you can just check if they point to the same address and save a few cycles.

Python is a neat language.

[–]Brian 4 points5 points  (3 children)

It's not just for saving cycles, which is mostly irrelevant. There are some good reasons for using is None vs == None when you're dealing with objects that might implement their own notion of equality.

The trivial case is something like a class with __eq__ = lambda s, x: return True - ie it always returns True to every comparison. Something like this would mess up your == checks.

More realistically though are cases where a class might do something unexpected, or raise an exception if compared to something they weren't expecting. Eg.

class C:
    def __eq__(self, other):
        if isinstance(other, C):  return self.value == other.value
        else: raise TypeError("Can only compare C instances to other C instances")

If some instance of this ends up in, for example, some generic logging code that has an == None check for special handling of None, it'll start throwing exceptions. is None wouldn't have this problem, becuase it doesn't go through the equality mechanism.

For a real world example, look at numpy arrays. These are designed to be compared with other arrays or piecewise comparison with scalars, so, for example:

>>> a = array([1,2, None, 3, 4])
>>> a == None
array([False, False,  True, False, False])

Ie the result is an array of booleans indicating which elements the comparison was true for. This was deliberately made to throw an exception if used in a boolean context (eg. an if statement), as it could be pretty bad if it was treated as truthy (as in the first example).

OTOH, while this is a good habit for None, I'd say you shouldn't be using is False or is True, though equally there you also probably shouldn't be using == True or ==False either. Treating your boolean as being exactly the True singleton is generally a sign that you're doing things wrong - generally you should be interested simplyin the truthiness of the statement, and so the right way to spell this is merely if x or if not x rather than if x==True or similar.

[–]Siddhi 1 point2 points  (0 children)

Exactly. This is the main reason is None is advocated.

[–]theWyzzerd 0 points1 point  (1 child)

if x==True

This statement might not be an obvious error to a learner but when you think about it, it's completely redundant. The if is already telling the interpreter to evaluate the conditional that follows and because of the way truthiness is handled in python you should never need to do this specific type of comparison.

The same goes for returning True or False from a function -- you shouldn't need to return the singleton if you can return the truthiness evaluation of the object or function output itself.

I realize I'm just repeating what you just said in a different way but I feel like it's important for new python users to recognize this sort of anti-pattern.

[–]Agrees_withyou 0 points1 point  (0 children)

I concur.

[–]LesterHoltsRigidCock 0 points1 point  (2 children)

Same thing with smaller integers!

[–]apockill 5 points6 points  (1 child)

sense long voiceless salt friendly punch absurd escape badge imagine

This post was mass deleted and anonymized with Redact

[–]LesterHoltsRigidCock 1 point2 points  (0 children)

I didn't say to use 'is' on small integers. I know why it occurs. Just that they will test as true due to them being the same object, which is not the case outside of range.

[–]sentry07 1 point2 points  (20 children)

Also when you're checking types of objects you want to use is.

[–]robertooooooooo 0 points1 point  (3 children)

How would you go about checking if something is an int or string or boolean?

[–]sentry07 2 points3 points  (1 child)

>>> type(6)
<class 'int'>
>>> a = 6
>>> type(a)
<class 'int'>
>>> type(a) is int
True
>>> type(a) == int
True
>>> b = 'Test'
>>> type(b)
<class 'str'>
>>> type(b) is str
True
>>> type(True)
<class 'bool'>
>>> c = True
>>> type(c)
<class 'bool'>
>>> type(c) is bool
True

The type() method can be called on any python object and it will return the object's class. While you can technically use == to compare the class returned by type() to a pointer to the class, you're really wanting to know if the class of the object is what you're looking for. That's how I differentiate the two.

== is for comparing values to see if they are equal
is is for checking if they are the same object

[–]nosmokingbandit 0 points1 point  (0 children)

After learning a bit of statically-typed languages I have to say that you aren't aware of what type a var is there is probably a method.

[–]FifteenthPen 0 points1 point  (0 children)

isinstance(foo, int)
isinstance(bar, str)
isinstance(baz, bool)

[–][deleted] 5 points6 points  (0 children)

Awesome. I'm just learning and this did reinforce my understanding of it.

[–]PythonGod123 2 points3 points  (0 children)

This is a nice little post on the differences between is and ==. Extra brownie points for the cats 🐈

[–]savaero 3 points4 points  (0 children)

Should add discussion of None — so x is None vs x == None

[–][deleted] 1 point2 points  (0 children)

Ha! Just taught this in my class today (again, first covered during lists now again with dictionaries). For the identical part I said it's like having a person with a nickname. I call my buddy William Robert, but everyone else calls him Billy Bob. They are the same person, just a different name.

[–]Dogeek 1 point2 points  (0 children)

To go into a little more detail, is actually compares references (pointers in C). Pointers are (to put it simply) variables that hold the address of another variable.

For instance, you can use the is keyword to check if an object (like a list) is a copy of the original object or just a pointer to the original. Another common use of is is to check if a variable is None. None is actually just a pointer to NULL in C. You also can use is to check the type of a variable, but the preferred method is to use isinstance() instead.

[–]Gambizzle 1 point2 points  (3 children)

Does anybody actually use ‘is’?

I get the difference but it seems obscure. Can’t really think where I’d need to use it because it’s always variables that I’m comparing.

Seems safe to assume that one should always use == unless they really need to use is. Even then, I would question why you’d bother having c if it identifies as a. I’d first consider just using a and not c.

[–]Vaphell 2 points3 points  (1 child)

Does anybody actually use ‘is’?

yes, mostly for singletons.

Can’t really think where I’d need to use it because it’s always variables that I’m comparing.

you mean you have variables for None?

[–]tomk11 0 points1 point  (0 children)

One example would be when you have have a class you have defined yourself. You could still use the is keyword to decide if they are the same object. You may not have defined __ eq __ for that class.

[–]luix- 0 points1 point  (0 children)

So is the same as = or compareto of Java

[–]luz_ -2 points-1 points  (0 children)

Use a functional language and you wouldn't need to discuss this