4

Given the following code:

a = '1'
if a == 1:
    print 'yes'
else:
    print 'no'

we get output as no.

How is Python comparing a string value to an int here (if a == 1)? In C such a comparison would give an error because this is comparing different types.

Dimitris Fasarakis Hilliard
  • 150,925
  • 31
  • 268
  • 253
sans0909
  • 395
  • 7
  • 20

1 Answers1

6

Python is not C. Unlike C, Python supports equality testing between arbitrary types.

There is no 'how' here, strings don't support equality testing to integers, integers don't support equality testing to strings. So Python falls back to the default identity test behaviour, but the objects are not the same object, so the result is False.

See the Value comparisons section of the reference documentation:

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).

If you wanted to compare integers to strings containing digits, then you need to convert the string to an integer or the integer so a string, then compare.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • Out of curiosity, how does this square with other behaviors where there is type coercing: e.g. `3 is 3.0 == False` but `(3 == 3.0) == True` (I'm not suggesting strings should be coerced, but I'm more asking about the final sentence in your quote.) – brianpck Nov 03 '16 at 14:00
  • @brianpck: that's a *chained comparison*, which is the same thing as `3 is 3.0 and 3.0 == False`. The first expression is **not** the same thing as the second. – Martijn Pieters Nov 03 '16 at 14:02
  • @brianpck: see [Why does the expression 0 < 0 == 0 return False in Python?](//stackoverflow.com/q/6074018) – Martijn Pieters Nov 03 '16 at 14:02
  • Sorry, I meant to write `(3 is 3.0) == False` In other words, `is` and `==` do *not* imply each other. – brianpck Nov 03 '16 at 14:04
  • @MartijnPieters thank you so much for the answer, Just wanted to confirm when you say the same identity does it mean the same address? – sans0909 Nov 03 '16 at 14:04
  • 1
    @sanyesh: yes, when two names refer to the same object; in that case `id(op1)` will be the same as `id(op2)`. It is the same test as `op1 is op2`. – Martijn Pieters Nov 03 '16 at 14:06
  • @brianpck: integers explicitly support comparison to other numeric types, so the default `==` behaviour doesn't apply there. `==` **can** support a wider notion of equality (functional equality), so `==` returning `True` does not imply that `is` will produce `True`. – Martijn Pieters Nov 03 '16 at 14:11
  • @MartijnPieters could you also please explain this scenario?...... consider we have mutable data type like list say, list1 = [1,2,3] and list2 = [1,2,3].... we know id(list1) != id(list2). Now if we use conditional statement like--- if list1 == list2: print 'yes' else: print 'No' , How is python going to compare this? – sans0909 Nov 03 '16 at 14:50
  • 1
    @sanyesh: do check up on the documentation I already linked to: *Sequences compare lexicographically using comparison of corresponding elements, whereby reflexivity of the elements is enforced.* The lists are equal because their contents are equal. – Martijn Pieters Nov 03 '16 at 14:52
  • This is wrong. Identity testing is used when the type doesn't provide its own `__eq__` *at all*. In this case, the one from `object` is used. However, since `str` does provide `__eq__` (in order to compare to other strings), it needs to check the type explicitly, and explicitly give a `False` result when the type of the other object isn't `str`. – Karl Knechtel Sep 03 '22 at 23:11
  • 1
    @KarlKnechtel: nope, see the source code: `strv.__eq__(intv)` [returns `NotImplemented`](https://github.com/python/cpython/blob/50a70a083d34305a52fac4f5901bff2ead152d68/Objects/unicodeobject.c#L10598-L10599). It is the [`==` operator implementation](https://github.com/python/cpython/blob/b9634ac776c24bc4d4a57859d884a94cdfe16043/Objects/object.c#L654-L703) that then tries `(intv).__eq__(strv)` in the reverse operation, which [also returns `NotImplemented`](https://github.com/python/cpython/blob/b126196838bbaf5f4d35120e0e6bcde435b0b480/Objects/longobject.c#L3155), before using identity equality. – Martijn Pieters Sep 10 '22 at 12:11
  • @KarlKnechtel: in `do_richcompare()`, when both objects returned `Py_NotImplemented`, the fallback is to use `res = (v == w) ? Py_True : Py_False;`, which compares pointers => an identity check. – Martijn Pieters Sep 10 '22 at 12:32
  • I was looking at the source code, but it's more subtle than I thought. – Karl Knechtel Sep 10 '22 at 18:36