7

this line evaluates to True in python

False in [0,1,2]

because False and 0 are equal after typecasting. Is there any way to avoid this typecasting? Something like === operator for list?

(I know that I can handle this case with a loop by explicitly checking for value types, but I am curious if there is some short and sweet trick to do this without a loop).

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
baba26
  • 939
  • 1
  • 7
  • 10
  • 4
    There is no typecasting in Python. `bool` is a *subclass of `int`*. – Martijn Pieters Oct 26 '17 at 08:43
  • Yup, unfortunately this is the case because of how False and True are defined. – bouteillebleu Oct 26 '17 at 08:44
  • Refer to this previous [post](https://stackoverflow.com/questions/27431249/python-false-vs-0). So this suggests that you would have to run a for loop / list comprehension. – Sanyam Mehra Oct 26 '17 at 08:44
  • And some more details here: https://stackoverflow.com/questions/2764017/is-false-0-and-true-1-in-python-an-implementation-detail-or-is-it-guarante – doctorlove Oct 26 '17 at 08:45
  • 2
    If by `===` operator, you mean something like the Javascript `===` operator, then that is the equivalent to the Python `==` operator. No implicit type conversions are going on, if that is what you mean by typecasting. Python is strongly typed, there is no need. It is just that *bools are ints*. – juanpa.arrivillaga Oct 26 '17 at 08:47
  • To back up what @juanpa.arrivillaga said, both `"1"==str(1)` and `int("1") ==1` evaluate to `True`, but `"1" == 1` is `False`. – Arthur Tacca Oct 26 '17 at 08:50
  • 1
    @bouteillebleu there were quite some debates wrt/ adding a `bool` type in Python, with a large minority standing against this decision and IIRC not even a clear majority being explicitely in favor of this addition. The BDFL finally decided to add it nonetheless, with some design choices dictated by compatibilty issues (look at pep 285 for more on this). Given that Python never actually _needed_ a boolean type (and still don't need it), I think the design choices were as good as possible. – bruno desthuilliers Oct 26 '17 at 09:04
  • Indeed it is a duplicate. – cs95 Oct 26 '17 at 09:33

3 Answers3

10

First of all, there is no typecasting in Python. False == 0 is true because bool is a subclass of int, and the two objects really are equal.

And no, there is no === operator, you need to explicitly test for types if you don't want this to happen:

lst = [....]
testvalue = False
if any(testvalue == elem and type(testvalue) is type(elem) for elem in lst):
    # lst contains testvalue and it is the same type

This explicitly asserts that the two objects are the exact same type, disallowing for subclasses.

Yes, this is a loop. But in for a list also uses a loop, only internally, and both the in containment check and any() short circuit, they return True as soon as the first match is found.

Note that this would disallow float equality too. 0.0 == 0 is true too, but by testing for exact types you disallow that as well. The same goes for complex numbers, and Decimal():

>>> 0j == 0 == 0.0 == Decimal('0')
True

bool is just another numeric type here, albeit one limited to the numeric values 0 and 1.

The better approach, going forward, is to use type hinting in your code; the type hints checker would catch issues like you using booleans where integers or numbers are expected.

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
8

If you really feel the need to do the same you can as follows.

False in filter(lambda x: isinstance(x, bool), [0, 1, 2])

Or as @JonClements suggested

any(x is False for x in [0, 1, 3]) # Since immutable values (including 
                                   # boolean) are instantiated only once.

However, such use case seldom arises where you need to differentiate between 0 and False as both are falsy as far as Python is concerned. Perhaps, you need to re-think your use-case.

hspandher
  • 15,934
  • 2
  • 32
  • 45
1

You can use "is" keyword for this.

>>> False == 0
True
>>> False is 0
False
Naresh Chaudhary
  • 705
  • 5
  • 14