28

The Python use of 'is' seems to be similar to JavaScript '===' but not quite.

Here they talk about exact instances: http://www.learnpython.org/en/Conditions

here (for JS) they talk about "equal AND the same type." http://www.w3schools.com/js/js_comparisons.asp

SO can you have two different instances of (say) a string of "Bob" and have them not return true when compared using 'is'? Or is it infact the same as ===?

I am guessing this is related to strict vs non-strict typed languages. . . .

R Claven
  • 1,160
  • 2
  • 13
  • 27
  • This doesn't have to do with types, `is` tests object identity (i. e. whether two names (or other references) refer to the same object (residing at the same address in memory)), whereas `==` checks if the objects compare equal. (`1 == 1.0`). – Tim Pietzcker Feb 14 '14 at 08:55
  • 1
    Related: [`is` operator behaves differently when comparing strings with spaces](http://stackoverflow.com/questions/16756699/is-operator-behaves-differently-when-comparing-strings-with-spaces) – Ashwini Chaudhary Feb 14 '14 at 08:56
  • @TimPietzcker It does for the JS side AFAIK. User-defined objects can't overload `==` or `===`, and JavaScript's predefined notion of equality *is* object identity, i.e. for objects (as opposed to primitives), JavaScript's `===` does act like Python's `is`. –  Feb 14 '14 at 08:57
  • 1
    @delnan: As far as I know, `===` does not check object identity, it just checks if they are of equal value and of equal type. But they may reside at different memory addresses. – Tim Pietzcker Feb 14 '14 at 09:00
  • 1
    @TimPietzcker [Nope](http://stackoverflow.com/q/21488340/395760). It's actually quite hard to define (deep) value equality for arbitrary object graphs correctly, it's a potential performance hog, and "equal type" is also a fuzzy concept (is it the prototype? do we take inheritance into account? is it the set of members? do the types of the members influence the "type"?). Edit: Note that in JS, things like numbers and strings are not objects. I explicitly restricted myself to objects (user-defined ones, even, though this is probably redundant). –  Feb 14 '14 at 09:03
  • @delnan: But for example item 5. in the linked docs suggests that strings don't have to be the same object, just compare equal (plus there are many strange cases like comparisons with `Null` or `undefined` always returning `True`. See also Sean Viera's answer below - there seems to be a need for an `is`-like operator in JavaScript. (My usage of `object` in the above comment was meant to refer to an object in the Python sense, not a JavaScript `object`. Sorry for the confusion) – Tim Pietzcker Feb 14 '14 at 09:09
  • @TimPietzcker I edited the last comment just now. I'm only talking about objects. Strings are not objects as far as JS is concerned. –  Feb 14 '14 at 09:10
  • in JS, ({valueOf: function(){return 5}}) == 5 is true but ({valueOf: function(){return 5}}) === 5 is false... – dandavis Feb 14 '14 at 09:18
  • @TimPietzcker @delnan Please check my answer. I have included the actual algorithm used by JavaScript engines to evaluate `===`. – thefourtheye Feb 14 '14 at 09:25

4 Answers4

29

Python Part

SO can you have two different instances of (say) a string of "Bob" and have them not return true when compared using 'is'? Or is it infact the same as ===?

a = "Bob"
b = "{}".format("Bob")
print a, b
print a is b, a == b

Output

Bob Bob
False True

Note: In most of the Python implementations, compile time Strings are interned.

Another example,

print 3 is 2+1
print 300 is 200+100

Output

True
False

This is because, small ints (-5 to 256) in Python are cached internally. So, whenever they are used in the programs, the cached integers are used. So, is will return True for them. But if we choose bigger numbers, like in the second example, (300 is 200+100) it is not True, because they are NOT cached.

Conclusion:

is will return True only when the objects being compared are the same object, which means they point to the same location in memory. (It solely depends on the python implementation to cache/intern objects. In that case, is will return True)

Rule of thumb:

NEVER use is operator to check if two objects have the same value.


JavaScript Part

Other part of your question is about === operator. Lets see how that operator works.

Quoting from ECMA 5.1 Specs, The Strict Equality Comparison Algorithm is defined like this

  1. If Type(x) is different from Type(y), return false.
  2. If Type(x) is Undefined, return true.
  3. If Type(x) is Null, return true.
  4. If Type(x) is Number, then
    1. If x is NaN, return false.
    2. If y is NaN, return false.
    3. If x is the same Number value as y, return true.
    4. If x is +0 and y is −0, return true.
    5. If x is −0 and y is +0, return true.
    6. Return false.
  5. If Type(x) is String, then return true if x and y are exactly the same sequence of characters (same length and same characters in corresponding positions); otherwise, return false.
  6. If Type(x) is Boolean, return true if x and y are both true or both false; otherwise, return false.
  7. Return true if x and y refer to the same object. Otherwise, return false.

Final Conclusion

We can NOT compare Python's is operator and JavaScript's === operator, because Python's is operator does only the last item in the Strict Equality Comparison Algorithm.

7. Return true if x and y refer to the same object. Otherwise, return false.
Eggcellentos
  • 1,570
  • 1
  • 18
  • 25
thefourtheye
  • 233,700
  • 52
  • 457
  • 497
  • The "rule of thumb" is actually the whole definition of `is`. And that's not the part that needs a rule pf thumb ;-) –  Feb 14 '14 at 08:59
  • In Python 3 your example gives True True as the result as compared to Python 2.7. – Parth Sane Dec 10 '19 at 19:15
5
>>> a = "Hello, World!!!"
>>> b = "Hello, World!!!"
>>> a is b
False

However note that:

>>> a = "Bob"
>>> b = "Bob"
>>> a is b
True

In this case it condition was True because the compiler is free to intern string literals, and thus reuse the same object, and it does do that with small strings. However there is no guarantee as to when this happens of if this happens at all and the behaviour changes between versions and implementations.


A realiable False output should be:

>>> a = 'Hello, World!!!!'[:-1]
>>> b = 'Hello, World!!!!'[:-1]
>>> a is b
False

Or anything that actually computes the strings.

Bakuriu
  • 98,325
  • 22
  • 197
  • 231
5

Completely different.

>>> a = 'foo'
>>> b = 'bar'
>>> a + b is 'foobar'
False
>>> 1000 + 1 is 1001
False
Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
  • The insidious part is that there are many naive tests which *do* output `True`. No answer on the topic is complete without debunking those. –  Feb 14 '14 at 08:53
5

Python's is keyword compares references (and so is about identity) while === does a minimal amount of coercion (and is therefore concerned with equality, at least in the case of primitives) so they are different.

As I understand it, things that are concerned with identity are concerned with uniqueness from the runtime's point of view (do these two variables point to the same address in memory) while equality is concerned with the uniqueness of the contents of the variables (are these two variables equivalent, regardless of where they are placed in memory relative to each other).

Sean Vieira
  • 155,703
  • 32
  • 311
  • 293
  • I'm surprised by that discussion (link please?) as the differences only show in "primitive"/non-Object types, which are special anyway and don't appear to have an identity as such. Sure, there are boxed equivalents and those can probably be constructed implicitly, but since this would create separate wrapper objects for both arguments that makes it a long-winded way of not considering any primitives equal to any other primitives. Am I missing something? –  Feb 14 '14 at 09:07
  • @delnan - true, it does only affect primitives, but sometimes you reference semantics for variables that might hold a primitives like `NaN` or `0`. Compare `===` with [`SameValue`](http://people.mozilla.org/~jorendorff/es6-draft.html#sec-samevalue) - `NaN` is `NaN` but it does not equal `NaN`, while `-0` is not `+0` but they are equal. Does that make sense (it's very late / early for me here, so I might be talking through my hat). – Sean Vieira Feb 14 '14 at 09:42