Strict comparison

Question:

In javascript, there are strict comparison operators op1 === op2 and op1 !== op2 that will compare both type and value. Is there a pythonic way of achieving the same thing?

So far I’ve only been able to come up with the following messy conditionals:

isinstance(op1, type(op2)) and isinstance(op2, type(op1)) and op1 == op2

and

not isinstance(op1, type(op2)) or not isinstance(op2, type(op1)) or op1 != op2
Asked By: Gillespie

||

Answers:

Your approach would indeed check both value and type. There isn’t a different operator in Python.

This having been said, in many cases that’s not what you want – in Python’s philosophy any object that behaves as a duck should be treated as a duck. You often don’t want only dictionaries, you want “mapping-like” objects and so on – as long as the object can be used for the particular task then the code should accept it.

Answered By: Simeon Visser

Python’s equal comparator is for the most part always strict.

For example:

Python

0 == '0'  # False
0 == ''  # False

Javascript

0 == '0'  //True
0 === '0'  //False
0 == ''  //True
0 === '0' //False
Answered By: Nick Humrich

Python’s equal comparator is strict except for when comparing 1 to True, and 0 to False, and it doesn’t matter if the value for 1 or 0 is of type float, decimal.Decimal, or long. Zero of any numeric type, for example, 0, 0L, 0.0, 0j is always False. (Note that anything else cast to a bool is True. See Truth Value Testing in Python.) 1 of any type except complex (1L, 1.0, 1) is always True.

In Python:

0 == '0'  # False
0 == '0' and type(0) == type('0')  # False, compare short circuits 
0 == ''  # False
0 == '' and type(0) == type('')  # False, compare short circuits 

1 == True and type(1) == type(True)  # False, makes a difference here
1 == True  # True, also true if 1 was 1.00, etc..
0 == False  # True
False == None  # False
0 == bool(None)  # True

When the first comparison returns False, the second one is not evaluated, hence it short circuits because 0 and anything else is 0. This is unnecessary though, it would only apply to when comparing 1 to True in line 6.

In JavaScript:

0 == '0'  //true
0 === '0'  //false
0 == ''  //true
0 === '0' //false

1 === true //false
1 == true //true
0 == false //true
false == null //false
0 == !!(null) //true

So the closest thing to the JavaScript === in Python is:

a == b and type(a) == type(b)

But only would need to be used in the case of a boolean comparison to 1 or 0, which is unlikely. If you expect a value to be either a numeric or a boolean, you might want to fix your code. A rookie mistake is to have something like this occur:

a = 0.0  # a valid value, lets assume it comes from a source that can also return None and we have no control over that.

# Should be:
# if a not None:
if a: # a is cast to bool, bool(0.0) is False
    print "do something here..."

Just to clear up some confusion, its good to be aware of Python’s is operator. Python has a is operator which returns True if both sides of the is are bound to the same object, otherwise it returns False. When using string literals, the lifetime of the objects is only for the instance of the statement. So performing is on string literals is safe since if they are the same, they are assigned to the same object. This also applies to other immutable types like bool, and all number types:

0 is '0'  # False
0 is False  # False
0 is 0  # True

This is not guaranteed to work when comparing two variables or a variable and a literal.

When you create two empty lists you get two different objects, so is returns False:

x = []
y = []
x is y  # False

But in this case, these variables reference the same list, and will continue to do so until they are re-assigned, or a deep copy is made of one from the other:

x = y = []
x is y  # True
x.append(1)
x is y  # True
x = [1, ]
x is y  # False, even though the value is same

The is operator is comparing the identities of the objects, it is performing the following:

id('0') == id(0)

So if both objects reference the same memory, they reference the same object and therefore must be the same.

Its a good idea to avoid is to make strict comparisons unless you want to check if both objects are referencing the same memory.

As Simon’s answer states, Python’s philosophy on equality differs from JavaScript’s and there really is no need for a strict equality comparator. Python’s equality comparator is not loose like JavaScripts == but at the same time its not exactly the same as ===.

You should be okay with Python’s equality comparator as long as its clear to you that zero of any numeric type (0, 0L, 0.0, 0j) is always equal to False and 1 of any numeric type except complex numbers (1, 1L, 1.0) is True.

Answered By: radtek

EDIT: You cannot create a new operator, python doesn’t support that. However operators are effectively functions anyway, and you can (I believe) override them.

If you are comparing primitives, then often you can use is instead, even though it is not strictly the same as what you are asking. There are some gotchas, but it will "generally work".

If you are not comparing primitives and you have made two classes, you can control how they compare equality.

Original Post:

You can also use the operator module if you want to be super strict.
https://docs.python.org/2/library/operator.html

>>> import operator
>>> operator.eq(True, 1)
True
>>> operator.is_(True, 1)
False

Some of the answers in here are wrong. Python for instance, will not differentiate between some types, for the purpose of some comparisons.

For example:

>>> 1 == 1.0
True
>>> operator.eq(1, 1.0)
True
>>> operator.is_(1, 1.0)
False

Is works better than eq (or ==), but it is dependent on a variable being pointers on the same value, which means there’s lots of cases you wouldn’t like.

If you want to go deep, implementing this in a shorthand manner, something like this: http://code.activestate.com/recipes/384122/ will let you "kind of" build your own operators.

Answered By: TinBane

In python there is only one strict comparison operator that is ==
Suppose we have 2 cases:

>>> 2 == '2'
False

# Comparison of Int with string, it returns False
>>> 2 == 2.0
True

# Comparison of Int with Float, it returns True

However in other programming languages like Julia, There is a distinction between comparison operator and strict comparison operator.

>>> 2 == 2.0
true

>>> 2 === 2.0
false

# strict comparison operator, namely === which is true only if two values agree fully as to type as well as value.
Answered By: Siddhesh Shankar
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.